<?php

namespace App\Service\OpenShop;

use App\Enums\Check\CheckEnum;
use App\Enums\OpenShop\AreaBaseEnum;
use App\Enums\OpenShop\BaseErrorCode;
use App\Enums\OpenShop\InvestmentPromotion\ErrCode;
use App\Enums\OpenShop\InvestmentPromotion\MainProcessEnum;
use App\Enums\OpenShop\InvestmentPromotion\OrganizationManageEnum;
use App\Enums\OpenShop\InvestmentPromotion\SignOrderEnum;
use App\Enums\OpenShop\InvestmentPromotion\SignOrderErrorTrait;
use App\Enums\OpenShop\InvestmentPromotion\SiteLocationEnum;
use App\Enums\OpenShop\InvestmentPromotion\SiteMissionEnum;
use App\Enums\OpenShop\InvestmentPromotion\UploadFileResourceEnum;
use App\Enums\OpenShop\InvestmentPromotion\UserContractEnum;
use App\Enums\OpenShop\InvestmentPromotion\UserOrderEnum;
use App\Enums\OpenShop\MissionTemplateEnum;
use App\Enums\Pay\RmsPayEnum;
use App\Enums\Workflow\WorkflowEnum;
use App\Events\OpenShop\OrderClosedEvent;
use App\Exceptions\Custom\CustomHttpResponseException;
use App\Exceptions\Custom\ResponseHttpException;
use App\Http\Resources\OpenShop\InvestmentPromotion\OrderDetailResource;
use App\Http\Resources\OpenShop\InvestmentPromotion\OrderManagerResource;
use App\Http\Resources\OpenShop\InvestmentPromotion\ProcessDetailResource;
use App\Http\Resources\OpenShop\InvestmentPromotion\UserContractResource;
use App\Http\Resources\OpenShop\ShopLocation\OrderPayHistoryResource;
use App\Http\Resources\OpenShop\ShopLocation\PlaceHolderSiteLocationResource;
use App\Http\Validate\OpenShop\InvestmentPromotion\OrderNewValidate;
use App\Library\FeiShu\SendFs;
use App\Library\Rms\RmsShopApi;
use App\Library\Rms\RmsUserApi;
use App\Models\Check\CheckCmbBankFlow;
use App\Models\Common\ConfigModel;
use App\Models\Common\OperateLogModel;
use App\Models\Common\ResourcesModel;
use App\Models\Cruise\CruiseOrderInputModel;
use App\Models\Cruise\CruiseOrderModel;
use App\Models\Cruise\CruiseTemplateModel;
use App\Models\Ekb\EkbApplyHistoryModel;
use App\Models\Kms\User\KmsUser;
use App\Models\OpenShop\Common\OpenShopOrderManagerModel;
use App\Models\OpenShop\Common\SupplierShopCodeRelModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopContractTemplateModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopLocationModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopMainProcessModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopOrderTagsMappingModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopOrganizationManageModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopPreparationOrderRefundModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopProcessDetailModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopProcessDetailNoticeEmployeeModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopSignOrderLogModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopSignOrderModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopSignOrderPayHistoryModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopSignOrderPermissionAnchorModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopSiteMissionModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopSpaceDesignCostMappingModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopSpaceDesignModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopSpaceDesignSoftOutfitMappingModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopUserBaseInfoModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopUserContractModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopUserExtContractModel;
use App\Models\OpenShop\ShopCheckAccept\OpenShopCheckAcceptModel;
use App\Models\OpenShop\ShopEngineeringConstruction\OpenShopEngineeringConstructionModel;
use App\Models\OpenShop\SiteLocation\OpenShopSiteLocationModel;
use App\Models\OpenShop\StartBusiness\OpenShopStartBusinessModel;
use App\Remote\EKuaiBao\EKuaiBaoRemote;
use App\Remote\Feishu\FeishuAuthRemote;
use App\Remote\Feishu\FeishuMsgRemote;
use App\Remote\Feishu\Tools\MsgTagBuild\ImgTagMsgBuild;
use App\Remote\Feishu\Tools\MsgTagBuild\TextTagMsgBuild;
use App\Remote\Feishu\Tools\TextMsgBuildTools;
use App\Remote\Rms\RmsAreaRemote;
use App\Remote\Rms\RmsShopRemote;
use App\Remote\Rms\RmsUserRemote;
use App\Service\BaseService;
use App\Service\Check\CmbBank\CmbAccountService;
use App\Service\Common\CommonService;
use App\Service\OpenShop\Feishu\ConfigService;
use App\Service\OpenShop\Feishu\KfosService;
use App\Service\OpenShop\Feishu\MainProcessService;
use App\Service\OpenShop\Feishu\NoticeService;
use App\Service\OpenShop\Feishu\OrderManagerService;
use App\Service\OpenShop\Feishu\OrganizationManageService;
use App\Service\OpenShop\Feishu\PermissionService;
use App\Service\OpenShop\Feishu\SelectionService;
use App\Service\OpenShop\Feishu\ShopCheckAcceptService;
use App\Service\OpenShop\Feishu\ShopEngineeringConstructionService;
use App\Service\OpenShop\Feishu\ShopManualService;
use App\Service\OpenShop\Feishu\SiteMissionService;
use App\Service\OpenShop\Feishu\SpaceDesignService;
use App\Service\OpenShop\Feishu\StartBusinessService;
use App\Service\OpenShop\Feishu\UserExtContractService;
use App\Service\OpenShop\Order\OrderTagsService;
use App\Service\OpenShop\SiteLocation\PlaceHolderSiteLocationService;
use App\Service\OpenShop\SiteLocation\SiteLocationService;
use App\Service\OpenShop\User\RmsUserService;
use App\Service\OpenShop\Wap\SignOrderService;
use App\Service\Rms\ShopService;
use App\Service\Workflow\WorkflowHandlerUserService;
use App\Support\ChangeSupport;
use Barryvdh\DomPDF\Facade\Pdf;
use Dompdf\Options;
use Exception;
use Guanguans\Notify\Factory;
use Guanguans\Notify\Messages\FeiShu\CardMessage;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Psr7\Utils;
use Illuminate\Contracts\Filesystem\FileNotFoundException;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\ValidationException;
use Kuafu\File\PrivateFileUtil;
use Kuafu\GeneralFs\BuildFs;
use Kuafu\Qiyuesuo\request\DocumentDownloadRequest;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use function Symfony\Component\Translation\t;

/**
 * @author Green Leaf <786407418@qq.com>
 */
class OrderService extends BaseService
{

    /**
     * 获取用户合同信息
     *
     * @param OpenShopSignOrderModel $openShopSignOrderModel
     * @return mixed
     */
    public static function getOrderContract(OpenShopSignOrderModel $openShopSignOrderModel)
    {
        return $openShopSignOrderModel->allOrderDetailContractRel->map(function (
            OpenShopUserContractModel $userContractModel
        ) {
            return array_merge(
                [],
                $userContractModel->only(["id", "categoryName", "categoryId", "detailStatus", "signTime", "contractType"]),
                [
                    "extContract" => $userContractModel->userExtContractRel->map(function (
                        OpenShopUserExtContractModel $extContractModel
                    ) {
                        return [
                            'contractId'    => $extContractModel->contractId,
                            'contractExtNo' => $extContractModel->contractExtNo,
                            'contractName'  => $extContractModel->contractName,
                            'contractUrl'   => $extContractModel->contractUrl,
                            'previewUrl'    => privateFilePath($extContractModel->previewUrl),
                            'downloadUrl'   => privateFilePath($extContractModel->downloadUrl),
                            'signStatus'    => $extContractModel->signStatus,
                            'createdAt'     => $extContractModel->createdAt->timestamp > 0 ? formatDate($extContractModel->createdAt->timestamp) : '-',
                            'signTime'      => formatDate($extContractModel->signTime),
                        ];
                    })
                ]
            );
        })->values()->toArray();
    }

    /**
     * @param string $orderNo
     * @param int $dataPermission
     * @param bool $isApp
     * @return array
     * @throws ContainerExceptionInterface
     * @throws GuzzleException
     * @throws NotFoundExceptionInterface
     */
    public static function detail(string $orderNo, int $dataPermission = 0, bool $isApp = false): array
    {
        try {
            // 根据订单号去处理
            $permissionList = null;
            if (!$isApp) {
                $permissionObj = (new PermissionService);

                // isAll && 原生sql
                $orderPermission = $permissionObj->getOrderPermissionDataOrder($dataPermission, getRmsUserId());

                if ($orderPermission['rawSql'] == 'id=0') {
                    Log::warning("detail no permission: orderNo:{$orderNo} dataPermission:{$dataPermission} userId:" . getRmsUserId());
                }

                // 具体的orderNo list
//                if (!$permissionObj->getOrderNoLists()->count()) {
//                    throw new CustomHttpResponseException(ErrCode::errCodeTrans(BaseErrorCode::BASE_CODE_DETAIL_FAIL));
//                }

                $permissionList = getRmsUserPermissionList();
            }

            $orderDetail = OpenShopSignOrderModel::orderDetail(
                $orderNo,
                true,
                true,
                true,
                true,
                false,
                true,
                true,
                true,
                $dataPermission,
                true,
                true,
                true,
                true,
                true
            );

            $processDetail = OpenShopProcessDetailModel::query()
                                                       ->where(
                                                           "mainProcessId",
                                                           $orderDetail->getIterator()->current()->mainProcessId
                                                       )
                                                       ->orderBy("id", "desc")
                                                       ->get();

            $shopLocation = $orderDetail->getIterator()->current()->shopLocationRel ?: null;
            if ($shopLocation) {
                ($shopLocation->openTime = formatDate($shopLocation->openTime));
                $shopLocation->shopLocationReportUrl = privateFilePath($shopLocation->shopLocationReportUrl);
                $imgList                             = SelectionService::getImgList($orderNo);
                $shopLocation['imgMapping']          = $imgList;
                // 获取门店名称

                $shopName                 = SiteMissionService::getRmsShopNameByCode([
                        $orderDetail->getIterator()->current()->shopCode
                    ])['shopList'][0]['name'] ?? "还没有店名";
                $shopLocation['shopName'] = $shopName;
            }


            $shopLocationReport = OpenShopSiteLocationModel::query()
                                                           ->where('orderNo', $orderNo)
                                                           ->whereIn('source',
                                                               [
                                                                   OpenShopSiteLocationModel::SOURCE_OPEN_SHOP,
                                                                   OpenShopSiteLocationModel::SOURCE_HOUSING
                                                               ])
                                                           ->with([
                                                               'uploadFileResourceRel' => function ($query) {
                                                                   $query->where('position',
                                                                       UploadFileResourceEnum::THE_CASH_REGISTER_PHOTO);
                                                               }
                                                           ])
                                                           ->first();
            $siteLocationId     = 0;
            if ($shopLocationReport) {
                $siteLocationId = $shopLocationReport->id;
                $budgeting      = SiteLocationService::getCapitalBudgetingPrice($shopLocationReport);
                //选址日均营收
                $shopLocationReport->monthTurnoverEstimation = (int)(($budgeting['monthTurnoverEstimation'] ?? 0) / 30);
                //选址日均保本点
                $shopLocationReport->dailyTurnover = $budgeting['dailyTurnover'] ?? 0;
                $shopLocationReport->openTime      = formatDate($shopLocationReport->openTime);
                // 获取门店名称
                $notice                               = new NoticeService($orderNo);
                $shopName                             = $notice->getShopName();
                $shopLocationReport->shopName         = $shopName;
                $shopLocationReport->currentFormat    = SiteLocationEnum::CURRENT_FORMAT_TYPE_TEXT[$shopLocationReport->currentFormat] ?? '-';
                $shopLocationReport->isHave           = SiteLocationEnum::MESSAGE_MYSELF_HAVE_MAPPING[$shopLocationReport->messageFrom] ?? '-';
                $shopLocationReport->messageFrom      = SiteLocationEnum::MESSAGE_FROM_TYPE_TEXT[$shopLocationReport->messageFrom] ?? '-';
                $shopLocationReport->caseRegisterType = SiteLocationEnum::CASE_REGISTER_TEXT[$shopLocationReport->caseRegisterType] ?? '-';
                $restrictedSalesArr                   = explode(',', $shopLocationReport->restrictedSales);
                $restrictedSales                      = [];
                foreach ($restrictedSalesArr as $value) {
                    $restrictedSales[] = SiteLocationEnum::RESTRICTED_SALES_TEXT[$value] ?? '-';
                }
                $shopLocationReport->restrictedSales = implode(',', $restrictedSales);
                //计租方式
                $shopLocationReport->fixedRentText = SiteLocationEnum::RENT_TYPE_TEXT[$shopLocationReport->rentType] ?? '-';
                //租金支付周期
                $shopLocationReport->rentPaymentCycle = SiteLocationEnum::RENT_PAYMENT_MONTH[$shopLocationReport->rentPaymentCycle] ?? '-';
                //装修店型
                $shopLocationReport->decorationShopType = SiteLocationEnum::DECORATION_SHOP_TEXT[$shopLocationReport->decorationShopType] ?? '-';
                //电量增容
                $shopLocationReport->isCapacityIncrease = SiteLocationEnum::IS_CAPACITY_INCREASE_TEXT[$shopLocationReport->isCapacityIncrease] ?? '-';
                //排风改造
                $shopLocationReport->isExhaustReconstruction = SiteLocationEnum::IS_EXHAUST_RECONSTRUCTION_TEXT[$shopLocationReport->isExhaustReconstruction] ?? '-';
                //水管改造
                $shopLocationReport->isReformWater = SiteLocationEnum::IS_EXHAUST_RECONSTRUCTION_TEXT[$shopLocationReport->isReformWater] ?? '-';
                //空调
                $shopLocationReport->airConditionerCType = SiteLocationEnum::AIR_CONDITIONER_TYPE_TEXT[$shopLocationReport->airConditionerCType] ?? '-';
                //消防
                $shopLocationReport->isFireControl = SiteLocationEnum::IS_FIRE_CONTROL_TEXT[$shopLocationReport->isFireControl] ?? '-';
                //店型
                $shopLocationReport->siteType = SiteLocationEnum::SITE_TYPE_TEXT[$shopLocationReport->siteType] ?? '-';

                //收银机凭证
                $cashTypeMapping = [];
                if ($shopLocationReport->uploadFileResourceRel) {
                    foreach ($shopLocationReport->uploadFileResourceRel as $item) {
                        $cashTypeMapping[] = $item->formatUrl;
                    }
                }
                $shopLocationReport->cashTypeMapping = $cashTypeMapping;
            }

            //获取订单经理信息
            $orderManage = $orderDetail
                ->getIterator()
                ->current()
                ->orderManagerRel
                ->where("orderStatus", OpenShopOrderManagerModel::ORDER_STATUS_NORMAL)
                ->where("isDeleted", OpenShopOrderManagerModel::NORMAL);

            $rmsUserIds = array_unique(array_filter(array_merge(
                $orderManage->isEmpty() ? [] : $orderManage->pluck("managerUid")->toArray(),
                $processDetail->isEmpty() ? [] : $processDetail->pluck("createdByUid")->toArray()
            )));

            $rmsUserInfo                    = (object)(empty($rmsUserIds) ? [] : RmsUserRemote::getRmsUserByIds($rmsUserIds));
            $rmsUserInfoCollection          = collect($rmsUserInfo)->keyBy("id");
            ProcessDetailResource::$rmsUser = $rmsUserInfoCollection;

            if ($orderDetail->getIterator()->current()->invalidContractRel) {
                UserContractResource::$signOrderUserExtContract = $orderDetail->getIterator()
                                                                              ->current()->invalidContractRel->userExtContractRel;
            }

            //订单信息
            $currentOrderDetail = OrderDetailResource::collection($orderDetail)->getIterator()->current();

            // 支付流水明细
            $payHistory = OpenShopSignOrderPayHistoryModel::query()
                                                          ->where('orderNo', $orderNo)
                                                          ->where('payStatus',
                                                              OpenShopSignOrderPayHistoryModel::PAY_STATUS_OK)
                                                          ->groupBy('sysType')
                                                          ->select("sysType", DB::raw('sum(payPrice) as sumPayPrice'))
                                                          ->get()
                                                          ->keyBy('sysType');

            // 获取设备支付
            // 判断是否是子单
            $openMain = OpenShopMainProcessModel::query()->where('orderNo', $orderNo)->first();

            // 设备支付金额
            $equipmentPayAll = OpenShopSignOrderPayHistoryModel::query()
                                                               ->when($openMain->childLocationOrder === 0,
                                                                   function ($query) use ($openMain) {
                                                                       $orderList = OpenShopMainProcessModel::query()
                                                                                                            ->select(['orderNo'])
                                                                                                            ->where('locationPid',
                                                                                                                $openMain->id)
                                                                                                            ->orWhere('id',
                                                                                                                $openMain->id)
                                                                                                            ->get()
                                                                                                            ->pluck('orderNo');
                                                                       $query->whereIn('orderNo', $orderList);
                                                                   }, function ($query) use ($orderNo) {
                                                                       $query->where('orderNo', $orderNo);
                                                                   })
                                                               ->where('sysType', 6)
                                                               ->where('payStatus',
                                                                   OpenShopSignOrderPayHistoryModel::PAY_STATUS_OK)
                                                               ->sum('payPrice');

            // 设备模块实付
            $equipmentPayActual = $equipmentPayAll ?? 0;

            // 设备模块应付
            if ($orderDetail->getIterator()->current()->shopCode) {
                $equipmentPayShould = (int)collect(KfosService::myEquipments($orderNo))->map(function ($v) {
                    return bcmul(bcmul($v["num"], 100), $v["saleUnitPrice"]);
                })->values()->sum();
            } else {
                $equipmentPayShould = 0;
            }

            if ($equipmentPayShould == 0 && $equipmentPayActual > 0) {
                $equipmentPayShould = $equipmentPayActual;
            }

            $tagLocationStatus = false;
            if ($orderDetail->getIterator()->current()->mainProcessRel->childLocationOrder == 0) {
                if (OpenShopMainProcessModel::query()->where('locationPid',
                    $orderDetail->getIterator()->current()->mainProcessRel->id)->exists()) {
                    $tagLocationStatus = true;
                } else {
                    $tagLocationStatus = false;
                }
            } else {
                if (count($orderDetail->getIterator()->current()->mainProcessRel->getRelationsLocationOrderNos())) {
                    $tagLocationStatus = true;
                }
            }


            $placeholder       = new PlaceHolderSiteLocationService($orderNo);
            $siteLocationInput = $siteLocationId ? (SiteLocationService::getSiteForm($siteLocationId, ['userId' => 0],
                    null, 1) ?? []) : [];
            if ((int)optional($shopLocationReport)->siteStatus == OpenShopSiteLocationModel::SITE_STATUS_4 && (int)optional($shopLocationReport)->signatureTime) {
                $leaseContractInfo                   = SiteLocationService::getLeaseContractForm($siteLocationId,
                        ['userId' => 0]) ?? [];
                $siteLocationInput['templateData'][] = $leaseContractInfo['templatedData'];
            }

            // 选址模块调整
            $emptyDetailStep = empty(StartBusinessService::detail($orderNo)["detail"]['step']);

            // 迁址单
            if ($openMain->getRelationsLocationOrderNos() && $openMain->nowStepStatus != MissionTemplateEnum::STEP_STATUS_999) {
                $reSite = true;
            } else {
                $reSite = false;
            }

            $preparationStatus  = OpenShopOrderTagsMappingModel::TAG_TYPE_1;                                             //筹备状态 1-正常 2-异常
            $preparationReason  = $preparationDesc = $preparationReasonText = $pendingTerminationText = '';              //异常标签和描述
            $tags               = [];                                                                                    //筹备标签
            $pendingTermination = $siteLocationPendingTermination = OpenShopOrderTagsMappingModel::TAG_TYPE_1;           //门店解约状态 1-正常 2-待解约
            if ($orderDetail->getIterator()->current()->tagsMappingRel) {
                collect($orderDetail->getIterator()->current()->tagsMappingRel)->map(
                    function ($item) use (&$preparationStatus, &$preparationReason, &$preparationDesc, &$tags, &$pendingTermination, &$preparationReasonText, &$siteLocationPendingTermination, &$pendingTerminationText) {
                        switch ($item->tagId) {
                            case OpenShopOrderTagsMappingModel::TAG_TYPE_1:
                            case OpenShopOrderTagsMappingModel::TAG_TYPE_2:
                                if ($item->tagId == OpenShopOrderTagsMappingModel::TAG_TYPE_2) {//筹备异常
                                    $preparationStatus = OpenShopOrderTagsMappingModel::TAG_TYPE_2;
                                }
                                $preparationReason     = $item->remark;
                                $preparationReasonText = '';
                                $preparationReasonTemp = explode(',', $item->remark);
                                if ($preparationReasonTemp) {
                                    $preparationReasonTextTemp = [];
                                    foreach ($preparationReasonTemp as $temp) {
                                        $preparationReasonTextTemp[] = OpenShopOrderTagsMappingModel::TAG_ABNORMAL_MAP_TEXT[$temp] ?? '';
                                    }
                                    $preparationReasonText = implode(',', $preparationReasonTextTemp);
                                }
                                $preparationDesc = $item->desc;
                                break;
                            case OpenShopOrderTagsMappingModel::TAG_TYPE_14:
                            case OpenShopOrderTagsMappingModel::TAG_TYPE_15:
                                if ($item->tagId == OpenShopOrderTagsMappingModel::TAG_TYPE_15) {//待解约
                                    $siteLocationPendingTermination = $pendingTermination = OpenShopOrderTagsMappingModel::TAG_TYPE_2;
                                    $tags[] = $pendingTerminationText = OpenShopOrderTagsMappingModel::TAG_TYPE_MAP_TEXT[$item->tagId] ?? "";
                                }
                                break;
                            case OpenShopOrderTagsMappingModel::TAG_TYPE_16://沉默客户
                                $siteLocationPendingTermination = OpenShopOrderTagsMappingModel::TAG_TYPE_3;
                                $pendingTerminationText = OpenShopOrderTagsMappingModel::TAG_TYPE_MAP_TEXT[$item->tagId] ?? "";
                                break;
                            case OpenShopOrderTagsMappingModel::TAG_TYPE_17://正常客户（A）- 定向选址
                            case OpenShopOrderTagsMappingModel::TAG_TYPE_18://沉默客户（A）- 高流失风险
                                $siteLocationPendingTermination = $item->tagId;
                                $pendingTerminationText = OpenShopOrderTagsMappingModel::TAG_TYPE_MAP_TEXT[$item->tagId] ?? "";
                                break;
                            default:
                                $tags[] = OpenShopOrderTagsMappingModel::TAG_TYPE_MAP_TEXT[$item->tagId] ?? "";

                        }
                    }
                );
            }
            $startBusiness = optional($orderDetail->getIterator()->current()->startBusinessRel)->startBusinessTime ?? 0;//正式开业时间
            $scheduledTime = $startBusiness > 0 ? date('Y-m-d', $startBusiness) : (
            optional($orderDetail->getIterator()->current()->siteLocationRel)->openTime ?
                date('Y-m-d', optional($orderDetail->getIterator()->current()->siteLocationRel)->openTime) : "-"
            );//预计开业时间 有开业时间显示开业时间

            //筹备信息
            $preparationInfo = [
                'isPreparation'         => in_array($currentOrderDetail->progressRel->nowStepStatus, MissionTemplateEnum::PREPARE_STATUS),                     //是否筹备中订单
                'scheduledTime'         => $scheduledTime,                                                                                                              //预计开业时间
                'preparationStatus'     => $preparationStatus,                                                                                                          //筹备状态
                'preparationStatusText' => OpenShopOrderTagsMappingModel::TAG_TYPE_MAP_TEXT[$preparationStatus] ?? "",                                                  //筹备状态文本
                'preparationReason'     => (string)$preparationReason,                                                                                                     //异常原因
                'preparationReasonText' => $preparationReasonText,                                                                                                      //异常原因文本
                'preparationDesc'       => $preparationDesc,                                                                                                            //异常原因描述
                'tagText'               => $tags,                                                                                                                       //标签文本
                "tagMapText"            => enumToSelection(OpenShopOrderTagsMappingModel::TAG_ABNORMAL_MAP_TEXT),
                'pendingTermination'    => $pendingTermination,                                                                                                          //门店解约状态 1-正常 2-待解约
                'shopAttributes'        => [
                    'shopType'        => optional($orderDetail->getIterator()->current()->siteLocationRel)->shopType ?? 0,        // 店型
                    'siteSelection'   => optional($orderDetail->getIterator()->current()->siteLocationRel)->siteSelection ?? '',  // 选址场景
                    'sellingCategory' => optional($orderDetail->getIterator()->current()->siteLocationRel)->sellingCategory ?? '',// 售卖品类
                    'posLine'         => optional($orderDetail->getIterator()->current()->siteLocationRel)->posLine ?? 0,         // 点餐动线
                    'menuLevel'       => optional($orderDetail->getIterator()->current()->siteLocationRel)->menuLevel ?? 0,       // 产品定价
                ],
            ];
            //选址 修改日志-取最新的日志内容
            $orderLog = OpenShopSignOrderLogModel::getInfoByOrderId(
                $orderDetail->getIterator()->current()->id,
                OpenShopSignOrderLogModel::SKIP_STEP_UPDATE_SITE_LOCATION_INFO
            );
            $logDesc = '';
            if ($orderLog) {
                $changes = $orderLog->changes ? json_decode($orderLog->changes, true) : [];
                if (isset($changes[0]['data']) && is_array($changes[0]['data'])) {
                    foreach ($changes[0]['data'] as $v) {
                        if ($v['key'] == 'text') {
                            $logDesc = $v['afterText'];
                        }
                    }
                }
            }
            $siteLocationDay       = 0;//选址累计耗时-最新一次指派开发经理到商家确认选址信息
            $siteLocationStartTime = optional($orderDetail->getIterator()->current()->siteMissionsRel)
                ->where('stepStatus', MissionTemplateEnum::STEP_STATUS_3)
                ->sortByDesc('id')->first();

            $siteLocationEndTime   = optional($orderDetail->getIterator()->current()->siteMissionsRel)
                ->where('stepStatus', MissionTemplateEnum::STEP_STATUS_5)
                ->sortByDesc('id')->first();
            if ($siteLocationStartTime) {
                $siteLocationStartTime = $siteLocationStartTime->toArray() ? $siteLocationStartTime->toArray()['createdAt'] : 0;
                $siteLocationEndTime   = $siteLocationEndTime && $siteLocationEndTime->toArray() ? $siteLocationEndTime->toArray()['completeAt'] : 0;
                $siteLocationDay       = $siteLocationStartTime ? (($siteLocationEndTime ? $siteLocationEndTime : time()) - strtotime($siteLocationStartTime)) / 86400 : 0;
                $siteLocationDay       = $siteLocationDay < 0 ? 0 : intval($siteLocationDay);
            } else {
                $siteLocationEndTime = '';
            }
            //选址信息
            $siteLocationInput['info'] = [
                'isSiteLocation'         => in_array($currentOrderDetail->progressRel->nowStepStatus, MissionTemplateEnum::SITE_STATUS),                 //是否选址中订单
                'pendingTermination'     => $siteLocationPendingTermination,                                                                                     //门店解约状态 1-正常 2-待解约 3-沉默客户
                'pendingTerminationText' => $siteLocationPendingTermination == 1 ? "正常" : $pendingTerminationText,                                              //门店解约状态 1-正常 2-待解约 3-沉默客户
                'siteLocationStartTime'  => $siteLocationStartTime ?? '-',                                                                                       //选址开始时间
                'siteLocationEndTime'    => $siteLocationEndTime ? date('Y-m-d H:i:s', $siteLocationEndTime) : '-',                                       //商家确认选址时间
                'siteLocationDay'        => $siteLocationDay,                                                                                                    //选址累计耗时-第一次指派开发经理到商家确认选址信息
                'userName'               => optional($orderDetail->getIterator()->current()->identityCardRel)->name,                                             //加盟商
                'siteLocationManager'    => optional($orderDetail->getIterator()->current()->siteLocationRel)->developConsultantName ?? 0,                       //选址负责人
                'logDesc'                => $logDesc,                                                                                                            //log详细
                'shopName'               => isset($shopLocation['shopName']) && $shopLocation['shopName'] ? $shopLocation['shopName'] : "",                      //门店名称
                'tagSiteLocationText'    => enumToSelection(OpenShopOrderTagsMappingModel::TAG_LIST_SITE_LOCATION_TEXT),                                   //选址中标签状态
            ];

            $mode = attributeGet($currentOrderDetail, "contractRel.mode", 0);

            // 判断主单子单
            $childOrder = $openMain->childOrder;
            if ($childOrder == MainProcessEnum::CHILD_ORDER_0) {

                // 主单加盟费-多店合计
                $mainProcessIds = OpenShopMainProcessModel::query()
                                                          ->where('pid', $openMain->pid)
                                                          ->where('childLocationOrder', MainProcessEnum::CHILD_ORDER_0)
                                                          ->pluck('id');

                $contractUser = OpenShopSignOrderModel::query()->where('orderNo', $orderNo)->first()->contractRel;
                if ($contractUser) {
                    $joinPayShould = (int)collect($contractUser->costLists())->sum('price');
                    $joinPayActual = (int)OpenShopSignOrderModel::query()->whereIn('mainProcessId', $mainProcessIds)->sum('payPrice');
                } else {

                    // 没合同
                    $joinPayShould = 0;
                    $joinPayActual = 0;
                }

            } else {

                // 子单加盟费直接0
                $joinPayShould = 0;
                $joinPayActual = 0;
            }

            return [
                "auth"                    => [
                    "designNewOrderBtn"     => in_array($openMain->compareStepStatusSort(MissionTemplateEnum::STEP_STATUS_14), ['>', '=']),
                    "softDesignNewOrderBtn" => in_array($openMain->compareStepStatusSort(MissionTemplateEnum::STEP_STATUS_17), ['>', '=']),
                    "equipmentNewOrderBtn"  => in_array($openMain->compareStepStatusSort(MissionTemplateEnum::STEP_STATUS_16), ['>', '=']),
                    "workClothesNewOrderBtn"  => in_array($openMain->compareStepStatusSort(MissionTemplateEnum::STEP_STATUS_7), ['>', '=']),

                    "designNewOrderTab"     => in_array($openMain->compareStepStatusSort(MissionTemplateEnum::STEP_STATUS_13), ['>', '=']),
                    "softDesignNewOrderTab"     => in_array($openMain->compareStepStatusSort(MissionTemplateEnum::STEP_STATUS_8), ['>', '=']),
                    "equipmentNewOrderTab"     => in_array($openMain->compareStepStatusSort(MissionTemplateEnum::STEP_STATUS_15), ['>', '=']),
                    "workClothesNewOrderTab"     => in_array($openMain->compareStepStatusSort(MissionTemplateEnum::STEP_STATUS_7), ['>', '=']),
                    "firstEquipmentOrderTab"     => in_array($openMain->compareStepStatusSort(MissionTemplateEnum::STEP_STATUS_7), ['>', '=']),
                ],
                "mode"                    => $mode,
                "modeText"                => OpenShopContractTemplateModel::MODE_MAP_TEXT[$mode] ?? "-",
                "userContract"            => self::getOrderContract($orderDetail->getIterator()->current()),
                "orderDetail"             => $currentOrderDetail,
                "shopLocation"            => $shopLocation,
                "shopLocationReport"      => $shopLocationReport,
                "processDetail"           => ProcessDetailResource::collection($processDetail),
                'manuals'                 => ShopManualService::getAllByOrderNo($orderNo),
                'spaceDesign'             => SpaceDesignService::handleSoftData($orderNo),
                'spaceDesignInfo'         => SpaceDesignService::getSpaceDesignMapping($orderNo),
                'checkAccept'             => ShopCheckAcceptService::detail($orderNo)["detail"],
                "engineeringConstruction" => ShopEngineeringConstructionService::detail($orderNo)["detail"],
                "orderManager"            => OrderManagerResource::collection(
                    $orderManage->map(function ($v) use ($rmsUserInfoCollection, $permissionList) {
                        $v->rmsUser = (object)$rmsUserInfoCollection[$v->managerUid] ?? (object)[];
                        $v->hasAuth = $permissionList && in_array(OpenShopOrderManagerModel::ORDER_CHANGE_MANAGER_MAPPING[$v->type],
                                $permissionList);
                        return $v;
                    })->sortBy("type")
                ),
                // 模块金额 - 应付
                "payDetail"               => [
                    "joinPay"   => $joinPayShould,
                    "designPay" => $currentOrderDetail->spaceDesignCostRel ? (int)$currentOrderDetail->spaceDesignCostRel
                        ->where('orderStatus', '!=', OpenShopSpaceDesignCostMappingModel::ORDER_STATUS_3)
                        ->sum("totalFee") : 0,

                    "designSoftPay" => $currentOrderDetail->spaceDesignSoftOutfitRel ? (int)$currentOrderDetail->spaceDesignSoftOutfitRel
                        ->where('orderStatus', '!=', OpenShopSpaceDesignSoftOutfitMappingModel::ORDER_STATUS_3)
                        ->sum("fee") : 0,
                    "equipmentPay"  => (int)$equipmentPayShould,
                ],

                // 模块金额 - 实付
                'payDetailActual'         => [
                    'joinPay'       => $joinPayActual,
                    'designPay'     => (int)($payHistory[CheckEnum::SYS_TYPE_OPEN_SHOP_DESIGN]['sumPayPrice'] ?? 0),
                    'designSoftPay' => (int)($payHistory[CheckEnum::SYS_TYPE_OPEN_SHOP_DECORATE]['sumPayPrice'] ?? 0),
                    'equipmentPay'  => (int)$equipmentPayActual,
                ],
                "startBusiness"           => StartBusinessService::detail($orderNo)["detail"],
                'shopSiteLocation'        => SiteLocationService::adminSiteLocation($orderNo),
                'siteLocationBoard'       => [
                    'replay'   => SiteLocationService::getReplayByOrderNo($orderNo, getRmsUserId()),
                    'approval' => SiteLocationService::getApprovalRecord($orderNo)
                ],

                // 选址模块调整
                'locationChange' => [
                    'dataChange'      => (!empty($shopLocationReport) && $emptyDetailStep) || $reSite,
                    'reSiteSelection' => (!empty($shopLocationReport) && $emptyDetailStep) || $reSite,
                    'rangeSetting'    => (!empty($shopLocationReport) && $emptyDetailStep) || $reSite,
                    'relocation'      => !empty($shopLocationReport) && !$emptyDetailStep,
                ],
                // 标签展示
                'tags'                    => self::getOrderTags(
                    0,
                    $tagLocationStatus,
                    $currentOrderDetail->contractStatus == OpenShopSignOrderModel::CONTRACT_STATUS_CHANGE,
                    $currentOrderDetail->dissolveStatus > OpenShopSignOrderModel::DISSOLVE_STATUS_NORMAL && $currentOrderDetail->status != SignOrderEnum::ORDER_STATUS_NO
                ),
                'generateContractBtn'     =>
                    $currentOrderDetail->step >= SignOrderEnum::STEP_4
                    &&
                    $currentOrderDetail->contractRel
                    &&
                    $currentOrderDetail->allContractRel
                    &&
                    $currentOrderDetail->allContractRel->where("contractType", UserContractEnum::CONTRACT_TYPE_8)->count() == 0
                    &&
                    empty($currentOrderDetail->contractRel->contractExtNo)
                    &&
                    $currentOrderDetail->dissolveStatus == OpenShopSignOrderModel::DISSOLVE_STATUS_NORMAL
                    &&
                    $openMain->childLocationOrder != MainProcessEnum::CHILD_ORDER_1
                ,

                'invalidContractBtn'      =>
                    $currentOrderDetail->step >= SignOrderEnum::STEP_4
                    &&
                    $currentOrderDetail->contractRel->contractStatus == OpenShopUserContractModel::CONTRACT_STATUS_NORMAL
                    &&
                    $currentOrderDetail->allContractRel
                    &&
                    $currentOrderDetail->allContractRel->where("contractType", UserContractEnum::CONTRACT_TYPE_8)->count() == 0
                    &&
                    !empty($currentOrderDetail->contractRel->contractExtNo)
                    &&
                    $currentOrderDetail->dissolveStatus == OpenShopSignOrderModel::DISSOLVE_STATUS_NORMAL
                    &&
                    $currentOrderDetail->contractStatus == OpenShopSignOrderModel::CONTRACT_STATUS_NORMAL
                ,
                'invalidOrderBtn'         => $currentOrderDetail->dissolveStatus == OpenShopSignOrderModel::DISSOLVE_STATUS_NORMAL,
                'siteLocationInput'       => $siteLocationInput,
                'placeholder'             => empty($placeholder->getPlaceholderInfo()) ? null :
                    PlaceHolderSiteLocationResource::collection([$placeholder->getPlaceholderInfo()])
                                                   ->getIterator()->current(),
                'preparationInfo' => $preparationInfo,//筹备信息
            ];

        } catch (Exception $e) {
            throw new CustomHttpResponseException(ErrCode::errCodeTrans((int)BaseErrorCode::BASE_CODE_DETAIL_FAIL), $e);
        }
    }


    /**
     * 作废订单
     *
     * @param int $uid
     * @param object $params
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface|ValidationException
     */
    public static function invalidOrder(int $uid, object $params)
    {
        try {
            $orderNo = $params->orderNo;
            $reason  = $params->reason;

            $signOrder = OpenShopSignOrderModel::getOrderDetailByOrderNo($params->orderNo);
            (clone $signOrder)->update([
                "invalidateType"  => attributeGet($params, "invalidateType", 0),
                "invalidedReason" => attributeGet($params, "reason", "")
            ]);
            $invalidType = self::getInvalidOrderType($signOrder);

            ChangeSupport::getInstance()->buildInsertChanges(
                "作废订单",
                (array)$params,
                array_merge(OrderNewValidate::getInstance()->getAttributes(), [
                    "contractType" => [
                        "type" => ChangeSupport::FILED_TYPE_ENUM,
                        "enum" => UserContractEnum::CONTRACT_TYPE,
                        "desc" => "合同类型"
                    ],
                    "invalidateType" => [
                        "type" => ChangeSupport::FILED_TYPE_ENUM,
                        "enum" => OpenShopSignOrderModel::INVALIDATE_TYPE_TEXT,
                        "desc" => "作废类型"
                    ]
                ])
            );

            ChangeSupport::getInstance()->batchChangesWriteToOrderLog(
                $signOrder->id,
                OpenShopSignOrderLogModel::INVALID_ORDER,
                getRmsUserInfoByAuth()->username ?? "",
                getRmsUserInfoByAuth()->id ?? 0
            );

            switch ($invalidType) {
                case OpenShopSignOrderModel::INVALID_TYPE_1:
                    OpenShopOrderManagerModel::invalidOrderManager($signOrder->mainProcessId);
                    Artisan::call(
                        "openShop:del-order",
                        [
                            "orderNo"  => $orderNo,
                            "delAll"   => 0
                        ]
                    );
                    break;
                case OpenShopSignOrderModel::INVALID_TYPE_2:
                    if (
                        $signOrder->contractRel
                        &&
                        $signOrder->contractRel->contractStatus == OpenShopUserContractModel::CONTRACT_STATUS_NORMAL
                        &&
                        !empty($signOrder->contractRel->contractExtNo)
                    ) {
                        throw new ResponseHttpException(SignOrderErrorTrait::$CONTRACT_SHOULD_BE_VALID);
                    }

                    OpenShopOrderManagerModel::invalidOrderManager($signOrder->mainProcessId);
                    Artisan::call(
                        "openShop:del-order",
                        [
                            "orderNo"  => $orderNo,
                            "delAll"   => 0
                        ]
                    );
                    break;
                case OpenShopSignOrderModel::INVALID_TYPE_3:
                case OpenShopSignOrderModel::INVALID_TYPE_4:
                    //解约
//                    if (
//                        $signOrder->contractRel->userExtContractRel->isNotEmpty()
//                        &&
//                        $signOrder->contractRel->userExtContractRel->getIterator()
//                                                                   ->current()->signTime < time()
//                        &&
//                        $signOrder->contractRel->userExtContractRel->getIterator()
//                                                                   ->current()->signTime + 7 * 24 * 60 * 60 > time()
//                    ) {
//                        if ($signOrder->contractRel->mode == OpenShopContractTemplateModel::MODE_2) {//分账模式
//                            $contractType      = UserContractEnum::CONTRACT_TYPE_7_KEY;
//                            $contractTypeValue = UserContractEnum::CONTRACT_TYPE_7;
//                        } else {
//                            $contractType      = UserContractEnum::CONTRACT_TYPE_5_KEY;
//                            $contractTypeValue = UserContractEnum::CONTRACT_TYPE_5;
//                        }
//                    } else {
//                        if ($signOrder->contractRel->mode == OpenShopContractTemplateModel::MODE_2) {//分账模式
//                            $contractType      = UserContractEnum::CONTRACT_TYPE_6_KEY;
//                            $contractTypeValue = UserContractEnum::CONTRACT_TYPE_6;
//                        } else {
//                            $contractType      = $signOrder->contractRel->version == 1 ? UserContractEnum::CONTRACT_TYPE_3_KEY : UserContractEnum::CONTRACT_TYPE_4_KEY;
//                            $contractTypeValue = $signOrder->contractRel->version == 1 ? UserContractEnum::CONTRACT_TYPE_3 : UserContractEnum::CONTRACT_TYPE_4;
//                        }
//                    }

                    list($contractType, $contractTypeValue) = self::getInvalidContractType($signOrder);
                    $userContractId = OpenShopUserContractModel::invalidOrderCopyRow(
                        $orderNo,
                        $contractTypeValue
                    );
                    $bizId          = vsprintf("%s-%s", [$orderNo, $userContractId]);

                    $generateContractResponse = UserExtContractService::commonGenerateContract(
                        $bizId,
                        "合同解约",
                        "{$orderNo} 解约",
                        $contractType,
                        UserExtContractService::commonBuildBuildSignatory($contractType, $signOrder, (array)$params),
                        UserExtContractService::commonBuildTemplateParams($contractType, $signOrder, (array)$params),
                        $orderNo
                    );

                    self::handleGenerateCancelContract(
                        $bizId,
                        $generateContractResponse["contractResponse"],
                        $generateContractResponse["signUrl"],
                        $invalidType == OpenShopSignOrderModel::INVALID_TYPE_3 ? OpenShopSignOrderModel::DISSOLVE_STATUS_CANCEL : OpenShopSignOrderModel::DISSOLVE_STATUS_CLOSE
                    );
                    break;
            }

            (new PlaceHolderSiteLocationService($orderNo))->clearPlaceHolder();

            // 过滤测试门店数据
            if ($signOrder->shopCode < OpenShopSignOrderModel::SHOP_CODE_TEST) {
                $provinceCode     = $signOrder->baseInfoRel->chooseShopProvinceCode;
                $organizationUser = OrganizationManageService::getProvinceInfoByProvinceCode($provinceCode);
                //作废通知到群
                $json = sprintf(
                    file_get_contents(resource_path('OpenShop/feishu/notifyTemplate/shopVoidTheContract.json')),
                    $signOrder->orderNo,
                    $signOrder->shopCode,
                    $signOrder->baseInfoRel->chooseShopAddressPrefix,
                    date('Y-m-d H:i:s'),
                    addslashes(OpenShopSignOrderModel::INVALIDATE_TYPE_TEXT[$params->invalidateType] ?? ""),
                    addslashes($reason),
                    ($organizationUser['operationName'] ?? '暂无省区总'),
                    '订单' . (OpenShopSignOrderModel::INVALID_TYPE_MAP[$invalidType] ?? '作废') . '通知'
                );
                self::sendVoidTheContract(json_decode($json, true));
            }

        } catch (Exception $e) {
            handleException($e);
        }
    }

    /**
     * @param OpenShopSignOrderModel $signOrderModel
     * @return array
     * @throws Exception
     */
    public static function getInvalidContractType(OpenShopSignOrderModel $signOrderModel): array
    {
        switch ($signOrderModel->contractRel->mode) {
            case OpenShopContractTemplateModel::MODE_2://分账模式解约合同
                $templateModel = attributeGet($signOrderModel, "contractRel.templateRel", null);
                if (empty($templateModel)) {
                    throw new Exception("获取合同政策模板失败 - {$signOrderModel->orderNo}");
                }
                if (str_contains($templateModel->templateName, "3%")) {
                    $contractType      = UserContractEnum::CONTRACT_TYPE_6_KEY;
                    $contractTypeValue = UserContractEnum::CONTRACT_TYPE_6;
                    break;
                }

                if (str_contains($templateModel->templateName, "10%")) {
                    $contractType      = UserContractEnum::CONTRACT_TYPE_7_KEY;
                    $contractTypeValue = UserContractEnum::CONTRACT_TYPE_7;
                    break;
                }

                throw new Exception("通过政策模板查询解约合同类型失败 - {$signOrderModel->orderNo}");
                break;
            default://传统模式解约合同
                //解约
                if (
                    $signOrderModel->contractRel->userExtContractRel->isNotEmpty()
                    &&
                    $signOrderModel->contractRel->userExtContractRel->getIterator()
                                                                    ->current()->signTime < time()
                    &&
                    $signOrderModel->contractRel->userExtContractRel->getIterator()
                                                                    ->current()->signTime + 7 * 24 * 60 * 60 > time()
                ) {
                    $contractType      = UserContractEnum::CONTRACT_TYPE_5_KEY;
                    $contractTypeValue = UserContractEnum::CONTRACT_TYPE_5;
                } else {
                    $contractType      = $signOrderModel->contractRel->version == 1 ? UserContractEnum::CONTRACT_TYPE_3_KEY : UserContractEnum::CONTRACT_TYPE_4_KEY;
                    $contractTypeValue = $signOrderModel->contractRel->version == 1 ? UserContractEnum::CONTRACT_TYPE_3 : UserContractEnum::CONTRACT_TYPE_4;
                }
                break;
        }

        return [$contractType, $contractTypeValue];
    }

    /**
     * 解约合同 - 回写
     *
     * @param string $bizId
     * @param array $contractResponse
     * @param string $signUrl
     * @param int $dissolveStatus
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public static function handleGenerateCancelContract(
        string $bizId,
        array $contractResponse,
        string $signUrl,
        int $dissolveStatus
    ) {
        list($orderNo, $contractId) = explode("-", $bizId);
        $orderDetail = OpenShopSignOrderModel::getOrderDetailByOrderNo($orderNo);

        OpenShopUserContractModel::query()->where("id", $contractId)->update([
            "categoryId"    => $contractResponse["category"]["id"],
            "categoryName"  => $contractResponse["category"]["name"],
            "contractExtNo" => $contractResponse["id"],
        ]);

        $userExtContractService = new UserExtContractService();
        $fileSystem             = app()->get('files');
        $dir                    = app()->storagePath() . "/" . date("Y-m-d");
        if (!$fileSystem->isDirectory($dir)) {
            $fileSystem->makeDirectory($dir, 0777, true);
        }

        OpenShopUserExtContractModel::query()->insert(
            collect($contractResponse["documents"])->map(function ($v) use (
                $orderDetail,
                $signUrl,
                $dir,
                $fileSystem,
                $userExtContractService,
                $contractId
            ) {
                $documentDownloadRequest = new DocumentDownloadRequest($v['id']);
                $filePath                = $dir . "/" . $v["id"] . ".pdf";
                $userExtContractService::handleResponse(
                    $userExtContractService->getSdkClient()->downloadService($documentDownloadRequest,
                        $filePath),
                    "契约锁合同转oss - 下载文件失败： 【 {$v["id"]} 】"
                );
                $ossInfo = PrivateFileUtil::uploadFile(
                    $filePath,
                    'pdf',
                    generateFileKey() . ".pdf"
                );
                $fileSystem->delete($filePath);

                return [
                    'contractId'    => $contractId,
                    'contractUrl'   => $signUrl,
                    'contractExtNo' => $v['id'],
                    'previewUrl'    => $ossInfo["path"],
                    'contractName'  => vsprintf("%s.%s-%s", ["No", $orderDetail->shopCode, $v['title']]),
                    'createdAt'     => time(),
                    'updatedAt'     => time()
                ];
            })->values()->toArray()
        );

        OpenShopSignOrderModel::query()
                              ->where("orderNo", $orderNo)
                              ->update(["dissolveStatus" => $dissolveStatus]);
    }

    /**
     * 解约合同 - 回写
     *
     * @param string $bizId
     * @param array $contractResponse
     * @param string $signUrl
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public static function handleGenerateCloseContract(string $bizId, array $contractResponse, string $signUrl)
    {
        list($orderNo, $contractId) = explode("-", $bizId);
        $orderDetail = OpenShopSignOrderModel::getOrderDetailByOrderNo($orderNo);

        OpenShopUserContractModel::query()->where("id", $contractId)->update([
            "categoryId"    => $contractResponse["category"]["id"],
            "categoryName"  => $contractResponse["category"]["name"],
            "contractExtNo" => $contractResponse["id"],
        ]);

        $userExtContractService = new UserExtContractService();
        $fileSystem             = app()->get('files');
        $dir                    = app()->storagePath() . "/" . date("Y-m-d");
        if (!$fileSystem->isDirectory($dir)) {
            $fileSystem->makeDirectory($dir, 0777, true);
        }

        OpenShopUserExtContractModel::query()->insert(
            collect($contractResponse["documents"])->map(function ($v) use (
                $orderDetail,
                $signUrl,
                $dir,
                $fileSystem,
                $userExtContractService
            ) {
                $documentDownloadRequest = new DocumentDownloadRequest($v['id']);
                $filePath                = $dir . "/" . $v["id"] . ".pdf";
                $userExtContractService::handleResponse(
                    $userExtContractService->getSdkClient()->downloadService($documentDownloadRequest,
                        $filePath),
                    "契约锁合同转oss - 下载文件失败： 【 {$v["id"]} 】"
                );
                $ossInfo = PrivateFileUtil::uploadFile(
                    $filePath,
                    'pdf',
                    generateFileKey() . ".pdf"
                );
                $fileSystem->delete($filePath);

                return [
                    'contractId'    => $orderDetail->contractRel->id,
                    'contractUrl'   => $signUrl,
                    'contractExtNo' => $v['id'],
                    'previewUrl'    => $ossInfo["path"],
                    'contractName'  => "No." . $orderDetail->shopCode . "-" . $v['title'],
                    'createdAt'     => time(),
                    'updatedAt'     => time()
                ];
            })->values()->toArray()
        );

        OpenShopSignOrderModel::query()->where("orderNo", $orderNo)
                              ->update(["dissolveStatus" => OpenShopSignOrderModel::DISSOLVE_STATUS_CANCEL]);
    }

    public static function getSelectionWait(int $orderStatus, int $pageNum, int $pageSize)
    {
        $openShopLocalBaseModel       = OpenShopLocationModel::query();
        $openShopDesignBaseModel      = OpenShopSpaceDesignModel::query();
        $openShopEngineeringBaseModel = OpenShopEngineeringConstructionModel::query();
        $openShopCheckBaseModel       = OpenShopCheckAcceptModel::query();
        $openShopStartBusinessModel   = OpenShopStartBusinessModel::query();
        $openShopUserContractModel    = OpenShopUserContractModel::query();
        switch ($orderStatus) {
            case UserOrderEnum::STEP_FORMAT_3: //开发待指派
                $selectionWait = $openShopLocalBaseModel
                    ->where('step', MainProcessEnum::SHOP_LOCATION_CHOOSE_MANAGER);
                break;
            case UserOrderEnum::STEP_FORMAT_4: // 选址待提交
                $selectionWait = $openShopLocalBaseModel
                    ->where('step', MainProcessEnum::SHOP_LOCATION_ASSIGN_MANAGER);
                break;
            case UserOrderEnum::STEP_FORMAT_5: // 商家待确认
                $selectionWait = $openShopLocalBaseModel
                    ->where('step', MainProcessEnum::SHOP_LOCATION_FORM_SUBMIT);
                break;
            case UserOrderEnum::STEP_FORMAT_6: // 建店信息待确认
                $selectionWait = $openShopDesignBaseModel
                    ->where('step', MainProcessEnum::SPACE_DESIGN_STEP_TYPE_PREPARATIONS_CONFIRM);
                break;
            case UserOrderEnum::STEP_FORMAT_7: // 设计师待指派
                $selectionWait = $openShopDesignBaseModel
                    ->where('step', MainProcessEnum::SPACE_DESIGN_STEP_TYPE_SPACE_DESIGN_ASSIGN_WAIT);
                break;
            case UserOrderEnum::STEP_FORMAT_8: // 设计图待提交
                $selectionWait = $openShopDesignBaseModel
                    ->where('step', MainProcessEnum::SPACE_DESIGN_STEP_TYPE_DESIGN_UPLOAD_FILE);
                break;
            case UserOrderEnum::STEP_FORMAT_9: // 进场待确认
                $selectionWait = $openShopEngineeringBaseModel
                    ->where('step', MainProcessEnum::ENGINEER_CONSTRUCT_STAY);
                break;
            case UserOrderEnum::STEP_FORMAT_10: // 施工待完成
                $selectionWait = $openShopEngineeringBaseModel
                    ->where('step', MainProcessEnum::ENGINEER_CONSTRUCT_START);
                break;
            case UserOrderEnum::STEP_FORMAT_11:  // 督导待指派
                $selectionWait = $openShopCheckBaseModel
                    ->where('step', MainProcessEnum::SHOP_CHECK_ASSIGN_MANAGER_STAY);
                break;
            case UserOrderEnum::STEP_FORMAT_12: // 督导待确认
                $selectionWait = $openShopCheckBaseModel
                    ->where('step', MainProcessEnum::SHOP_CHECK_ASSIGN_MANAGER);
                break;
            case UserOrderEnum::STEP_FORMAT_13: // 设计模块待确认
                $selectionWait = $openShopDesignBaseModel
                    ->where('step', MainProcessEnum::SPACE_DESIGN_STEP_TYPE_DESIGN_CONFIRM_DESIGN_MODULE);
                break;
            case UserOrderEnum::STEP_FORMAT_14: // 设计模块待支付
                $selectionWait = $openShopDesignBaseModel
                    ->where('step', MainProcessEnum::SPACE_DESIGN_STEP_TYPE_DESIGN_MODULE_PAY);
                break;
            case UserOrderEnum::STEP_FORMAT_15: // 设备模块待确认
                $selectionWait = $openShopDesignBaseModel
                    ->where('step', MainProcessEnum::SPACE_DESIGN_STEP_TYPE_DESIGN_CONFIRM_EQUIPMENT_MODULE);
                break;
            case UserOrderEnum::STEP_FORMAT_16: // 设备模块待支付
                $selectionWait = $openShopDesignBaseModel
                    ->where('step', MainProcessEnum::SPACE_DESIGN_STEP_TYPE_DESIGN_EQUIPMENT_PAY);
                break;
            case UserOrderEnum::STEP_FORMAT_17: // 软装待支付
                $selectionWait = $openShopDesignBaseModel
                    ->where('step', MainProcessEnum::SPACE_DESIGN_STEP_TYPE_SOFT_OUTFIT_PAY);
                break;
            case UserOrderEnum::STEP_FORMAT_18: // 开业报告待提交
                $selectionWait = $openShopStartBusinessModel
                    ->where('step', MainProcessEnum::START_BUSINESS_STAY);
                break;
            case MissionTemplateEnum::STEP_STATUS_100: // 待退款
                $selectionWait = $openShopUserContractModel
                    ->where('decorationDeposit', '!=', DB::raw('refundDecorationDeposit'))
                    ->where('decorationDeposit', '<>', 0)
                    ->where('updatedAt', '<>', 0)
                    ->where('createdAt', '<>', 0);
                break;
            default:
                return [];
        }
        $selectionWait = $selectionWait
            ->select(['orderNo'])
            ->orderBy('createdAt', 'desc')
//            ->limit($pageSize * $pageNum)
            ->pluck('orderNo')
            ->toArray();

        return $selectionWait;
    }

    public static function overview(array $orderPermission)
    {
        // 各阶段的订单状态汇总
        $stepCounts = MainProcessService::stepCount($orderPermission);

        $showStepStatusLists = collect($stepCounts)->map(function ($item) {
            return $item['ct'];
        });

        // 匿名方法，获取stepStatus数组的总count
        $countInStepStatus = function (array $stepStatusArr) use ($showStepStatusLists) {
            $count = 0;
            foreach ($showStepStatusLists as $stepStatus => $ct) {
                if (in_array($stepStatus, $stepStatusArr)) {
                    $count += $ct;
                }
            }

            return $count;
        };

        // 获取标签数据
        $tagCounts = OrderTagsService::getPrepareTagCountWithNowStepStatus($orderPermission, [
            MissionTemplateEnum::STEP_STATUS_3,
            MissionTemplateEnum::STEP_STATUS_4,
            MissionTemplateEnum::STEP_STATUS_5
        ]);

        $showTagStatusLists = collect($tagCounts)->map(function ($item) {
            return $item['ct'];
        });


        $lists = [
            [
                'text'          => '签约中',
                'lists'         => [
                    [
                        'text'          => '待支付',
                        'stepStatusStr' => (string)$stepStatus = MissionTemplateEnum::STEP_STATUS_1,
                        'count'         => $showStepStatusLists[$stepStatus] ?? 0,
                        'type'          => 'stepStatusStr',
                    ],
                    [
                        'text'          => '待签署',
                        'stepStatusStr' => (string)$stepStatus = MissionTemplateEnum::STEP_STATUS_2,
                        'count'         => $showStepStatusLists[$stepStatus] ?? 0,
                        'type'          => 'stepStatusStr',
                    ]
                ],
                'stepStatusStr' => implode(',', $stepStatusArr = [
//                    MissionTemplateEnum::STEP_STATUS_0,
                    MissionTemplateEnum::STEP_STATUS_1,
                    MissionTemplateEnum::STEP_STATUS_2,
                ]),
                'type'          => 'stepStatusStr',
                'count'         => $countInStepStatus($stepStatusArr),
            ],
            [
                'text'          => '选址中',
                'stepStatusStr' => implode(',', $stepStatusArr = [
                    MissionTemplateEnum::STEP_STATUS_3,
                    MissionTemplateEnum::STEP_STATUS_4,
                    MissionTemplateEnum::STEP_STATUS_5,
                ]),
                'lists'         => [
                    [
                        'parentStepStatusStr' => $stepStatusArr,
                        'stepStatusStr' => (string)$stepStatus = OpenShopOrderTagsMappingModel::TAG_TYPE_15,
                        'text'          => '待解约',
                        'count'         => $showTagStatusLists[$stepStatus] ?? 0,
                        'type'          => 'tagId',
                    ],
                    [
                        'parentStepStatusStr' => $stepStatusArr,
                        'stepStatusStr' => implode(',', [OpenShopOrderTagsMappingModel::TAG_TYPE_16, OpenShopOrderTagsMappingModel::TAG_TYPE_18]),
                        'text'          => '沉默客户',
                        'count'         => ($showTagStatusLists[OpenShopOrderTagsMappingModel::TAG_TYPE_16] ?? 0) + ($showTagStatusLists[OpenShopOrderTagsMappingModel::TAG_TYPE_18] ?? 0),
                        'type'          => 'tagId',
                    ],
                    [
                        'text'          => '商家待确认',
                        'stepStatusStr' => (string)$stepStatus = MissionTemplateEnum::STEP_STATUS_5,
                        'type'          => 'stepStatusStr',
                        'count'         => $showStepStatusLists[$stepStatus] ?? 0,
                    ],
                ],
                'count'         => $countInStepStatus($stepStatusArr),
                'type'          => 'stepStatusStr',
            ],
            [
                'text'          => '筹备中',
                'lists'         => [
                    [
                        'text'          => '设计模块待支付',
                        'stepStatusStr' => (string)$stepStatus = MissionTemplateEnum::STEP_STATUS_14,
                        'count'         => $showStepStatusLists[$stepStatus] ?? 0,
                        'type'          => 'stepStatusStr',
                    ],
                    [
                        'text'          => '设备模块待支付',
                        'stepStatusStr' => (string)$stepStatus = MissionTemplateEnum::STEP_STATUS_16,
                        'count'         => $showStepStatusLists[$stepStatus] ?? 0,
                        'type'          => 'stepStatusStr',
                    ],
                    [
                        'text'          => '软装待支付',
                        'stepStatusStr' => (string)$stepStatus = MissionTemplateEnum::STEP_STATUS_17,
                        'count'         => $showStepStatusLists[$stepStatus] ?? 0,
                        'type'          => 'stepStatusStr',
                    ]
                ],
                'stepStatusStr' => implode(',', $stepStatusArr = [
                    MissionTemplateEnum::STEP_STATUS_6,
                    MissionTemplateEnum::STEP_STATUS_7,
                    MissionTemplateEnum::STEP_STATUS_13,
                    MissionTemplateEnum::STEP_STATUS_14,
                    MissionTemplateEnum::STEP_STATUS_15,
                    MissionTemplateEnum::STEP_STATUS_16,
                    MissionTemplateEnum::STEP_STATUS_8,
                    MissionTemplateEnum::STEP_STATUS_17,
                    MissionTemplateEnum::STEP_STATUS_9,
                    MissionTemplateEnum::STEP_STATUS_10,
                    MissionTemplateEnum::STEP_STATUS_11,
                    MissionTemplateEnum::STEP_STATUS_12,
                ]),
                'count'         => $countInStepStatus($stepStatusArr),
                'type'          => 'stepStatusStr',
            ],
            [
                'text'          => '开业报告待提交',
                'lists'         => [],
                'stepStatusStr' => (string)$stepStatus = MissionTemplateEnum::STEP_STATUS_18,
                'count'         => $showStepStatusLists[$stepStatus] ?? 0,
                'type'          => 'stepStatusStr',
            ],
            [
                'text'          => '装修保证金待退',
                'lists'         => [],
                'stepStatusStr' => (string)$stepStatus = MissionTemplateEnum::STEP_STATUS_100,
                'count'         => $showStepStatusLists[$stepStatus] ?? 0,
                'type'          => 'stepStatusStr',
            ],
            [
                'text'          => '已营业',
                'lists'         => [],
                'stepStatusStr' => (string)$stepStatus = MissionTemplateEnum::STEP_STATUS_999,
                'count'         => $showStepStatusLists[$stepStatus] ?? 0,
                'type'          => 'stepStatusStr',
            ],
            [
                'text'          => '全部',
                'lists'         => [],
                'stepStatusStr' => '',
                'count'         => $showStepStatusLists['total'] ?? 0,
                'type'          => 'stepStatusStr',

            ],
            [
                'text'          => '已作废',
                'lists'         => [],
                'stepStatusStr' => (string)$stepStatus = MissionTemplateEnum::STEP_STATUS_102,
                'count'         => $showStepStatusLists[$stepStatus] ?? 0,
                'type'          => 'stepStatusStr',
            ],
            [
                'text'          => '解约',
                'lists'         => [],
                'stepStatusStr' => (string)$stepStatus = MissionTemplateEnum::STEP_STATUS_103,
                'count'         => $showStepStatusLists[$stepStatus] ?? 0,
                'type'          => 'stepStatusStr',
            ],
            [
                'text'          => '闭店',
                'lists'         => [],
                'stepStatusStr' => (string)$stepStatus = MissionTemplateEnum::STEP_STATUS_104,
                'count'         => $showStepStatusLists[$stepStatus] ?? 0,
                'type'          => 'stepStatusStr',
            ],
        ];

        return $lists;
    }

    public static function getlist(
        $province,
        $city,
        $area,
        $contractStartTime,
        $contractEndTime,
        $manager,
        $pageSize,
        $pageNum,
        $dataPermission,
        $shopCode,
        $merchantName,
        $orderNo,
        $stepStatusLists,
        $siteStartTime,
        $siteEndTime,
        $orderSource,
        $branch,
        $preparationUid,
        $reason,
        $scheduledStartTime,
        $scheduledEndTime,
        $preparationStartTime,
        $preparationEndTime,
        $startBusinessStartTime,
        $startBusinessEndTime,
        $preparationStartDay,
        $preparationEndDay,
        $tagId,
        $investmentManagerId,
        $inviterId,
        $departmentName,
        $mode,
        $shopPattern,
        $shopIds,
        int $investmentConsultantId
    )
    {
        if ($area) {
            $province = $city = '';
        }
        if ($city) {
            $province = '';
        }
        if ($branch && $branch != '全部' && !$province) {//分公司
            $getProvinces = (new OpenShopOrganizationManageModel)->getManageIdByBranch($branch);
            if ($getProvinces) {
                $province = array_column($getProvinces, 'provinceCode');
            }
        }
        // 根据订单号去处理
        $orderPermissionList = (new PermissionService)->getOrderPermissionDataOrder($dataPermission, getRmsUserId());
        $paginator = OpenShopSignOrderModel::query()
            ->join(
                'open_shop_user_contract as contract',
                'contract.orderNo', '=', 'open_shop_sign_order.orderNo'
            )
            ->when(
                !$orderPermissionList['isAll'],
                function ($query) use ($orderPermissionList) {
                    $query->whereRaw("open_shop_sign_order." . $orderPermissionList['rawSql']);
                }
            )
            ->when(strlen($shopPattern), function ($query) use ($shopPattern) {
                $shopPatternArr = explode(',', $shopPattern);
                if (count($shopPatternArr) == 1) {
                    switch ($shopPattern) {
                        case OpenShopSiteLocationModel::SHOP_PATTERN_TWO:
                            $query->whereRaw("open_shop_sign_order.orderNo in (select open_shop_site_locations.orderNo from open_shop_site_locations where shopPattern != 3 and source = 0 and isDeleted = 0)");
                            break;
                        case OpenShopSiteLocationModel::SHOP_PATTERN_THREE:
                            $query->whereRaw("open_shop_sign_order.orderNo in (select open_shop_site_locations.orderNo from open_shop_site_locations where shopPattern = 3 and source = 0 and isDeleted = 0)");
                            break;
                        default:
                    }
                }
            })
            ->when(
                $province || $city || $area,
                function ($query) use ($province, $city, $area) {
                    $query->join(
                        'open_shop_address as address', 'address.orderNo', '=',
                        'open_shop_sign_order.orderNo'
                    )
                        ->when(
                            $province, function ($q) use ($province) {
                            if (is_array($province)) {
                                $q->whereIn("address.provinceCode", $province);
                            } else {
                                $q->where("address.provinceCode", $province);
                            }
                        }
                        )
                        ->when(
                            $city, function ($q) use ($city) {
                            $q->where("address.cityCode", $city);
                        }
                        )
                        ->when(
                            $area, function ($q) use ($area) {
                            $q->where("address.areaCode", $area);
                        }
                        );
                }
            )
            ->when(
                mb_strlen($contractStartTime),
                function ($query) use ($contractStartTime, $contractEndTime) {
                    $query->whereBetween(
                        'open_shop_sign_order.signTime',
                        [$contractStartTime, $contractEndTime]
                    );
                }
            )
            ->when(
                mb_strlen($siteStartTime),
                function ($query) use ($siteStartTime, $siteEndTime) {
                    $orderList = OpenShopSiteMissionModel::query()
                        ->whereBetween(
                            'createdAt', [
                            $siteStartTime,
                            $siteEndTime
                        ]
                        )
                        ->where(
                            'stepStatus',
                            MissionTemplateEnum::STEP_STATUS_6
                        )
                        ->select(['orderNo'])
                        ->get()
                        ->pluck('orderNo');
                    $query->whereIn('open_shop_sign_order.orderNo', $orderList);
                }
            )
            ->when(
                mb_strlen($manager), function ($query) use ($manager) {
                $query->where('open_shop_sign_order.investmentManagerName', $manager);
            }
            )
            ->when(
                $shopCode, function ($query) use ($shopCode) {
                $query->where('open_shop_sign_order.shopCode', $shopCode);
            }
            )
            ->when(
                $merchantName || $shopIds, function ($query) use ($merchantName, $shopIds) {
                $query->join(
                    'open_shop_main_process as process', 'process.id', '=',
                    'open_shop_sign_order.mainProcessId'
                );
                $query->when(
                    $merchantName, function ($query) use ($merchantName) {
                    $query->join(
                        'open_shop_user_identity_card as identity',
                        'identity.orderNo', '=', 'process.orderNo'
                    )
                        ->where('identity.name', 'like', "%{$merchantName}%");
                }
                );
                $query->when(
                    $shopIds, function ($query) use ($shopIds) {
                    $query->whereIn('process.shopId', $shopIds);
                }
                );
            }
            )
            ->when(
                $orderNo, function ($query) use ($orderNo) {
                $query->where('open_shop_sign_order.orderNo', $orderNo);
            }
            )
            ->when(
                $investmentConsultantId > 0, function ($query) use ($investmentConsultantId) {
                $query->where('open_shop_sign_order.investmentManagerId', $investmentConsultantId);
            }
            )
            ->when(
                !count($stepStatusLists), function ($query) {
                $query->where('open_shop_sign_order.status', '!=', SignOrderEnum::ORDER_STATUS_NO);
            }
            )
            ->when(
                $stepStatusLists, function ($query) use ($stepStatusLists) {
                if ($stepStatusLists == [MissionTemplateEnum::STEP_STATUS_100]) {
                    $query
                        ->where(
                            'contract.decorationDeposit', '!=',
                            DB::raw('contract.refundDecorationDeposit')
                        )
                        ->where('contract.decorationDeposit', '<>', 0)
                        ->where(
                            'open_shop_sign_order.status',
                            SignOrderEnum::ORDER_STATUS_COMPLETE
                        );
                } elseif ($stepStatusLists == [MissionTemplateEnum::STEP_STATUS_101]) {
                    $query->where(
                        'disclosureStatus',
                        OpenShopSignOrderModel::DISCLOSURE_STATUS_OFF
                    )
                        ->where(
                            'open_shop_sign_order.status', '!=',
                            SignOrderEnum::ORDER_STATUS_NO
                        );
                } elseif ($stepStatusLists == [MissionTemplateEnum::STEP_STATUS_102]) {
                    $query->where(
                        'open_shop_sign_order.status',
                        SignOrderEnum::ORDER_STATUS_NO
                    );
                } elseif ($stepStatusLists == [MissionTemplateEnum::STEP_STATUS_999]) {
                    $query->where(
                        'open_shop_sign_order.status',
                        SignOrderEnum::ORDER_STATUS_COMPLETE
                    );
                } elseif ($stepStatusLists == [MissionTemplateEnum::STEP_STATUS_103]) {
                    $query->where(
                        'open_shop_sign_order.status', '=',
                        SignOrderEnum::ORDER_STATUS_NO
                    )->where(
                        "dissolveStatus",
                        OpenShopSignOrderModel::DISSOLVE_STATUS_CANCEL
                    );
                } elseif ($stepStatusLists == [MissionTemplateEnum::STEP_STATUS_104]) {
                    $query->where(
                        'open_shop_sign_order.status', '=',
                        SignOrderEnum::ORDER_STATUS_NO
                    )->where(
                        "dissolveStatus",
                        OpenShopSignOrderModel::DISSOLVE_STATUS_CLOSE
                    );
                } else {
                    $query->join(
                        'open_shop_main_process as process2', 'process2.id',
                        '=',
                        'open_shop_sign_order.mainProcessId'
                    )
                        ->whereIn('process2.nowStepStatus', $stepStatusLists)
                        ->where(
                            'open_shop_sign_order.status',
                            SignOrderEnum::ORDER_STATUS_OK
                        );
                }
            }
            )
            ->when(
                $preparationUid > 0,
                function ($query) use ($preparationUid) {
                    $query->join(
                        'open_shop_space_design', 'open_shop_space_design.orderNo', '=',
                        'open_shop_sign_order.orderNo'
                    );
                    $query->where("open_shop_space_design.preparationUid", $preparationUid);//筹备顾问搜索
                }
            )
            ->when(
                $investmentManagerId > 0,
                function ($query) use ($investmentManagerId) {
                    $query->join(
                        'open_shop_location', 'open_shop_location.orderNo', '=',
                        'open_shop_sign_order.orderNo'
                    );
                    $query->where("open_shop_location.investmentManagerId", $investmentManagerId);//开发顾问搜索
                }
            )
            ->when(
                $reason || ($tagId && $tagId != "" && is_array($tagId)),
                function ($query) use ($reason, $tagId) {
                    $query->join(
                        'open_shop_order_tags_mapping', 'open_shop_order_tags_mapping.orderNo', '=',
                        'open_shop_sign_order.orderNo'
                    );
                    if ($reason) {
                        $reasonTemp = explode(',', $reason);
                        $query->where(
                            function ($query) use ($reasonTemp) {
                                foreach ($reasonTemp as $reasons) {
                                    $query->orWhere('open_shop_order_tags_mapping.remark', 'like', "%{$reasons}%");//筹备异常原因搜索
                                }
                            }
                        );
                    }
                    if ($tagId && is_array($tagId)) {
                        $query->whereIn("open_shop_order_tags_mapping.tagId", array_values($tagId));//筹备标签Id搜索
                    }
                    $query->where("open_shop_order_tags_mapping.isDeleted", 0);//未删除
                }
            )
            ->when(
                $scheduledStartTime && $scheduledEndTime,
                function ($query) use ($scheduledStartTime, $scheduledEndTime) {
                    $query->join(
                        'open_shop_site_locations', 'open_shop_site_locations.orderNo', '=',
                        'open_shop_sign_order.orderNo'
                    );
                    $query->whereBetween("open_shop_site_locations.openTime", [$scheduledStartTime, $scheduledEndTime]);//预计开业时间搜索
                    $query->where("open_shop_site_locations.isDeleted", 0);//未删除
                }
            )
            ->when(
                ($preparationStartTime && $preparationEndTime) || ($preparationStartDay !== "" && $preparationEndDay !== ""),
                function ($query) use ($preparationStartTime, $preparationEndTime, $preparationStartDay, $preparationEndDay) {
                    $query->join(
                        'open_shop_site_mission', 'open_shop_site_mission.orderNo', '=',
                        'open_shop_sign_order.orderNo'
                    );
                    $query->where('open_shop_site_mission.stepStatus', MissionTemplateEnum::STEP_STATUS_6);
                    if ($preparationStartTime && $preparationEndTime) {
                        $query->whereBetween("open_shop_site_mission.createdAt", [$preparationStartTime, $preparationEndTime]);//筹备开始时间搜索
                    }
                    if ($preparationStartDay !== "" && $preparationEndDay !== "") {
                        $preparationEndDayStart = time() - (int)$preparationEndDay * 86400;
                        $preparationStartDayEnd = time() - (int)$preparationStartDay * 86400;
                        $query->whereBetween("open_shop_site_mission.createdAt", [$preparationEndDayStart - 86400, $preparationStartDayEnd]);//筹备累计耗时天数搜索 结尾多加一天 （天数不显示小数点）
                    }
                }
            )
            ->when(
                $startBusinessStartTime && $startBusinessEndTime,
                function ($query) use ($startBusinessStartTime, $startBusinessEndTime) {
                    $query->join(
                        'open_shop_start_business', 'open_shop_start_business.orderNo', '=',
                        'open_shop_sign_order.orderNo'
                    );
                    $query->whereBetween("open_shop_start_business.startBusinessTime", [$startBusinessStartTime, $startBusinessEndTime]);//开业时间选择搜索
                }
            )
            ->when(
                $inviterId || $departmentName,
                function ($query) use ( $inviterId, $departmentName) {
                    if ($inviterId) {
                        $query->where("contract.inviterId", $inviterId);//推荐人id搜索
                    }
                    if ($departmentName) {
                        $query->where("contract.departmentName", $departmentName);//部门名称搜索
                    }
                }
            )
            ->when($mode, function($query)use($mode){
                    $query->where("contract.mode", $mode);
            })
            ->with(
                [
                    'baseInfoRel',
                    'contractRel' => function ($q) {
                        $q->with(['templateRel'])
                            ->select();
                    },
                    'identityCardRel',
                    'progressRel',
                    'siteMissionsRel',
                    'addressRel',
                    'mainProcessRel',
                    'siteLocationRel',
                    'startBusinessRel',
                    'tagsMappingRel',
                    'spaceDesignRel',
                    'shopLocationRel'
                ]
            )
            ->groupBy('open_shop_sign_order.id')
            ->orderByDesc('open_shop_sign_order.createdAt')
            ->paginate($pageSize, ['open_shop_sign_order.*'], 'page', $pageNum);

        $mainProcessIds = $paginator->pluck('mainProcessId')->toArray();
        $provinceCodes  = array_unique(array_column(array_column($paginator->items(), 'addressRel'), 'provinceCode')) ?? [];//省份code
        $getBranch      = (new OpenShopOrganizationManageModel)->getBranchByProvinceCode($provinceCodes);                   //查询省份对应分公司
        if ($getBranch) {
            $getBranch = $getBranch->keyBy('provinceCode')->toArray();
        }
        $updatedByUids = array_unique(array_column(array_column($paginator->items(), 'baseInfoRel'), 'updatedByUid')) ?? [];//订单修改人
        $userInfos     = collect(RmsUserService::getRmsUserInfoByUserIds($updatedByUids)['data'])->keyBy('id'); //获取rms用户
        //获取开店订单重点城市列表-config
        $hotCity = Cache::remember('openShop:hotCity', getSwitchCacheTime(86400), function () {
            return json_decode(
                ConfigModel::query()
                           ->where('module', 'openShop')
                           ->where('name', 'hotCity')
                           ->value('value') ?? '', true
            );
        });
        $shopInfos = [];
        if ($orderSource) {
            $shopCodes = array_column($paginator->items(), 'kfShopCode');
            $shopInfos = collect(
                (new RmsShopApi())->getShopByCodes(
                    $shopCodes,
                    ['id', 'shopCode', 'name']
                )['data']['shopList'] ?? []
            )->keyBy('shopCode');//通过门店编号查询门店名称
        }

        $data    = [
            'count'    => $paginator->total(),
            'list'     => array_map(
                function (OpenShopSignOrderModel $v) use ($orderSource, $shopInfos, $userInfos, $getBranch, $hotCity, $mainProcessIds) {
                    $contractCode = optional($v->contractRel)->id;
                    if (null === $contractCode) {
                        $contractCode = '-';
                    }
                    $startTime = optional($v->contractRel)->startTime;
                    if (null === $startTime) {
                        $startTime = '-';
                    } else {
                        $startTime = date('Y-m-d', $startTime);
                    }
                    $branch       = '';//所属分公司
                    $provinceCode = optional($v->addressRel)->provinceCode;
                    if (null === $provinceCode) {
                        $provinceCode = '-';
                    } else {
                        if ($getBranch && isset($getBranch[$provinceCode])) {
                            $branch = $getBranch[$provinceCode]['name'];
                        }
                    }
                    $city = optional($v->addressRel)->cityCode;
                    if (null === $city) {
                        $city = '-';
                    }
                    $cityMark    = 0;//重点城市标记
                    $shopAddress = optional($v->addressRel)->addressPrefix;
                    if (null === $shopAddress) {
                        $shopAddress = '-';
                    } else {
                        if ($hotCity) {
                            foreach ($hotCity as $hotCityName) {
                                if (mb_strpos($shopAddress, $hotCityName) !== false) {//匹配网规重点城市
                                    $cityMark = 1;
                                    break;
                                }
                            }
                        }
                    }
                    $name = optional($v->identityCardRel)->name;
                    if (null === $name) {
                        $name = '-';
                    }
                    $endTime = optional($v->contractRel)->endTime;
                    if (null === $endTime) {
                        $endTime = '-';
                    } else {
                        $endTime = date('Y-m-d', $endTime);
                    }
                    $source = optional($v->baseInfoRel)->source;
                    if (null === $source) {
                        $source = '-';
                    }
                    $shopNum = optional($v->contractRel)->shopCount;
                    if (null === $shopNum) {
                        $shopNum = '-';
                    }
                    $exceptionMsg = optional($v->contractRel)->exceptionMsg;
                    $isAbnormal   = $exceptionMsg ? (json_decode($exceptionMsg, true)['message'] ?? '') : '';
                    $tagLocationStatus = false;
                    if (!empty(($v->mainProcessRel->childLocationOrder))) {
                        $tagLocationStatus = (bool)($v->mainProcessRel->childLocationOrder);
                    } else {
                        if (!empty($v->mainProcessRel) && count($v->mainProcessRel->getRelationsLocationOrderNos()) > 0) {
                            $tagLocationStatus = true;
                        }
                    }
                    $preparationStart     = optional($v->siteMissionsRel)->where('stepStatus', MissionTemplateEnum::STEP_STATUS_6)->sortByDesc('id')->first();   //筹备部确认建店信息 最新一条
                    $preparationStartTime = $preparationStart && $preparationStart->createdAt ? date('Y-m-d H:i:s', strtotime($preparationStart->createdAt)) : 0;//筹备开始时间
                    $startBusiness        = optional($v->startBusinessRel)->startBusinessTime ?? 0;                                                              //正式开业信息
                    if ($startBusiness) {
                        $preparationStartDay = (strtotime($startBusiness) - strtotime($preparationStartTime)) / 86400;                          //筹备累计耗时天数
                    } else {
                        $preparationStartDay = (time() - strtotime($preparationStartTime)) / 86400;                                             //筹备累计耗时天数
                    }
                    $preparationStartDay  = $preparationStartDay < 0 ? 0 : intval($preparationStartDay);
                    $preparationStatus    = OpenShopOrderTagsMappingModel::TAG_TYPE_1;                    //筹备状态 1-正常 2-异常
                    $pendingTermination   = OpenShopOrderTagsMappingModel::TAG_TYPE_1;                    //门店解约状态 1-正常 2-待解约
                    $preparationReason = $preparationDesc = $preparationReasonText = $pendingTerminationText = '';                  //异常标签和描述
                    $tags                 = [];
                    $isReticent = false;
                    collect($v->tagsMappingRel)->map(
                        function ($item) use (
                            $orderSource, &$preparationStatus, &$preparationReason, &$preparationDesc, &$tags, &$pendingTermination,
                            &$preparationReasonText, &$isReticent, &$pendingTerminationText
                        ) {
                            switch ($item->tagId) {
                                case OpenShopOrderTagsMappingModel::TAG_TYPE_1:
                                case OpenShopOrderTagsMappingModel::TAG_TYPE_2:
                                    if ($item->tagId == OpenShopOrderTagsMappingModel::TAG_TYPE_2) {//筹备异常
                                        $preparationStatus = OpenShopOrderTagsMappingModel::TAG_TYPE_2;
                                    }
                                    $preparationReason     = $item->remark;
                                    $preparationReasonText = '';
                                    $preparationReasonTemp = explode(',', $item->remark);
                                    if ($preparationReasonTemp) {
                                        $preparationReasonTextTemp = [];
                                        foreach ($preparationReasonTemp as $temp) {
                                            $preparationReasonTextTemp[] = OpenShopOrderTagsMappingModel::TAG_ABNORMAL_MAP_TEXT[$temp] ?? '';
                                        }
                                        $preparationReasonText = implode(',', $preparationReasonTextTemp);
                                    }
                                    $preparationDesc = $item->desc;
                                    break;
                                case OpenShopOrderTagsMappingModel::TAG_TYPE_14:
                                case OpenShopOrderTagsMappingModel::TAG_TYPE_15:
                                    if ($item->tagId == OpenShopOrderTagsMappingModel::TAG_TYPE_15) {//待解约
                                        $pendingTermination = OpenShopOrderTagsMappingModel::TAG_TYPE_2;
                                        $tags[]             = OpenShopOrderTagsMappingModel::TAG_TYPE_MAP_TEXT[$item->tagId] ?? "";
                                    }
                                    $pendingTerminationText = OpenShopOrderTagsMappingModel::TAG_TYPE_MAP_TEXT[$item->tagId];
                                    break;
                                case OpenShopOrderTagsMappingModel::TAG_TYPE_16:
                                    $pendingTermination     = OpenShopOrderTagsMappingModel::TAG_TYPE_3;//沉默客户
                                    $pendingTerminationText = OpenShopOrderTagsMappingModel::TAG_TYPE_MAP_TEXT[$item->tagId];
                                    $isReticent             = true;//沉默客户
                                    break;
                                case OpenShopOrderTagsMappingModel::TAG_TYPE_17:
                                    $pendingTermination     = OpenShopOrderTagsMappingModel::TAG_TYPE_17;//正常客户（A）- 定向选址
                                    $pendingTerminationText = OpenShopOrderTagsMappingModel::TAG_TYPE_MAP_TEXT[$item->tagId];
                                    break;
                                case OpenShopOrderTagsMappingModel::TAG_TYPE_18:
                                    $pendingTermination     = OpenShopOrderTagsMappingModel::TAG_TYPE_18;//沉默客户（A）- 高流失风险
                                    $pendingTerminationText = OpenShopOrderTagsMappingModel::TAG_TYPE_MAP_TEXT[$item->tagId];
                                    $isReticent             = true;//沉默客户
                                    break;
                                default:
                                    $tags[] = OpenShopOrderTagsMappingModel::TAG_TYPE_MAP_TEXT[$item->tagId] ?? "";

                            }
                        }
                    );


                    // 筹备工作台-增加最新跟进日志
                    $preparationLog = [];
                    if ($orderSource) {
                        $preparationLog = self::preparationLog('', $v->id, 1);
                    }
                    return [
                        'orderId'                => $v->id,
                        'orderNo'                => $v->orderNo,
                        'contractCode'           => $contractCode,
                        'shopCode'               => $v->kfShopCode ?: '-',
                        'shopName'               => $shopInfos && $v->shopCode ? ($shopInfos[$v->shopCode]['name'] ?? "") : '',
                        'area'                   => AreaBaseEnum::provinceCodeToRegion($provinceCode, $city),
                        'shopAddress'            => $shopAddress,
                        'addressDetail'          => optional($v->siteLocationRel)->address ?? "-",//选址报告-详细地址
                        'shopAddressCity'        => $shopAddress ? (implode('-', array_slice(explode('-', $shopAddress), 0, 2))) : "",//显示省-市
                        'name'                   => $name,
                        'signTime'               => $v->signTime ? date('Y-m-d H:i', $v->signTime) : '-',
                        'startTime'              => $startTime,
                        'endTime'                => $endTime,
                        'source'                 => ConfigService::getConfigText("openShop", "source", $source),
                        'shopNum'                => $shopNum,
                        'joiningPolicy'          => optional($v->contractRel)->templateRel->templateName ?? '-',
                        'scheduledTime'          => $startBusiness ? date('Y-m-d', $startBusiness) : (optional($v->siteLocationRel)->openTime ? date('Y-m-d', optional($v->siteLocationRel)->openTime) : "-"),//预计开业时间 有开业时间显示开业时间
                        'leasingManager'         => $v->investmentManagerName,
                        'openShopStatus'         => MissionTemplateEnum::STEP_STATUS_TEXT[$v->progressRel->nowStepStatus ?? '-'] ?? '',
                        'orderStatus'            => UserOrderEnum::STATUS_MAP[$v->status] ?? '-',
                        'childOrder'             => (int)optional($v->progressRel)->childOrder,
                        'isConfirm'              => ($v->step < SignOrderEnum::STEP_2) ? '合同待完善' : '',
                        'isDisclosure'           => $v->disclosureStatus ? '' : '信息披露单待完善',
                        'isAbnormal'             => $isAbnormal,
                        'isQuit'                 => OrderManagerService::getOrderManagerInfo(
                            $mainProcessIds,
                            $v->mainProcessId
                        ),
                        'step'                   => $v->step,
                        // 后续标签放置点
                        'tags'                   => self::getOrderTags(
                            0,
                            $tagLocationStatus,
                            $v->contractStatus == OpenShopSignOrderModel::CONTRACT_STATUS_CHANGE,
                            $v->dissolveStatus > OpenShopSignOrderModel::DISSOLVE_STATUS_NORMAL && $v->status != SignOrderEnum::ORDER_STATUS_NO,
                            false, false, false, false, $isReticent
                        ),
                        'startBusinessTime'      => $startBusiness ? date('Y-m-d', $startBusiness) : "-",                                                           //开业时间
                        'branch'                 => $branch,                                                                                                               //所属分公司名字
                        'cityMark'               => $cityMark,                                                                                                             //重点城市标记
                        'mobile'                 => optional($v->baseInfoRel)->mobile ?? "",                                                                               //加盟商电话
                        'preparationManager'     => (optional($v->spaceDesignRel)->preparationName) ?? "-",                                                                //筹备负责人，即筹备顾问
                        'preparationStartTime'   => $preparationStartTime,                                                                                                 //筹备开始时间
                        'preparationStartDay'    => $preparationStartDay,                                                                                                  //筹备累计耗时天数
                        'preparationStatus'      => $preparationStatus,                                                                                                    //筹备状态
                        'preparationStatusText'  => OpenShopOrderTagsMappingModel::TAG_TYPE_MAP_TEXT[$preparationStatus] ?? "",                                            //筹备状态文本
                        'preparationReason'      => (string)$preparationReason,                                                                                               //异常原因
                        'preparationReasonText'  => $preparationReasonText,                                                                                                //异常原因文本
                        'preparationDesc'        => $preparationDesc,                                                                                                      //异常原因描述
                        'tagText'                => $tags,                                                                                                                 //标签文本
                        'lastUpdateTime'         => optional($v->baseInfoRel)->updatedAt ? date('Y-m-d H:i:s', strtotime(optional($v->baseInfoRel)->updatedAt)) : "-",     //更新时间
                        'lastUpdateUser'         => $userInfos[optional($v->baseInfoRel)->updatedByUid]['username'] ?? "-",                                                 //更新人
                        'pendingTermination'     => $pendingTermination,                                                                                                   //门店解约状态 1-正常 2-待解约
                        'pendingTerminationText' => $pendingTerminationText,                                                                                        //门店解约状态文本
                        'investmentManagerName'  => (optional($v->shopLocationRel)->investmentManagerName) ?? "-",                                                  //招商经理名称，即开发顾问
                        'mode'                   => optional($v->contractRel)->mode ?? "-",          //加盟模式 1-传统模式 2分账模式
                        'modeText'               => OpenShopContractTemplateModel::MODE_MAP_TEXT[optional($v->contractRel)->mode ?? ""] ?? "-",     //加盟模式文本
                        'inviterId'              => optional($v->contractRel)->inviterId ?? "-",                                                    //邀请人id
                        'inviterName'            => optional($v->contractRel)->inviterName ?? "-",                                                  //邀请人名称
                        'departmentName'         => optional($v->contractRel)->departmentName ?? "-",                                               //部门名称
                        'preparationLog'         => $preparationLog,                                               //筹备日志
                        'shopPattern'            => (int)optional($v->siteLocationRel)->shopPattern,
                        'shopPatternStr'         => optional($v->siteLocationRel)->shopPattern ? (OpenShopSiteLocationModel::SHOP_PATTERN_MAPPING[optional($v->siteLocationRel)->shopPattern] ?? '-') : '-',
                        'patternType'            => optional($v->siteLocationRel)->patternType ? collect(explode(',', optional($v->siteLocationRel)->patternType))->map(function ($item) {
                            return (int)$item;
                        }) : [],
                        'patternTypeStr'         => OpenShopSiteLocationModel::getPatternTypeStr(optional($v->siteLocationRel)->patternType),

                        // 门店属性
                        'shopType'        => optional($v->siteLocationRel)->shopType ?? 0,        // 店型
                        'siteSelection'   => optional($v->siteLocationRel)->siteSelection ?? '',  // 选址场景
                        'sellingCategory' => optional($v->siteLocationRel)->sellingCategory ?? '',// 售卖品类
                        'posLine'         => optional($v->siteLocationRel)->posLine ?? 0,         // 点餐动线
                        'menuLevel'       => optional($v->siteLocationRel)->menuLevel ?? 0,       // 产品定价
                    ];
                }, $paginator->items()
            ),
            'pageNum'  => (int)$pageNum,
            'pageSize' => (int)$pageSize,
            "tagText"  => enumToSelection(OpenShopOrderTagsMappingModel::TAG_ABNORMAL_MAP_TEXT),
        ];
        if ($orderSource) {
            $data['prepareStatusText'] = enumToSelection(MissionTemplateEnum::PREPARE_STATUS_TEXT);//筹备中状态
        }
        return $data;
    }

    /**
     * 标签列表
     * @param int $platform 展示平台 0 web 1 飞书小程序
     * @param bool $locationStatus 是否迁址3
     * @param bool $changeContract 是否合同变更
     * @param bool $removeContract 是否解除协议签署中
     * @param bool $isAbnormal 是否异常
     * @param bool $isConfirm 合
     * @param bool $isDuoShop 多
     * @param bool $isQuit 离
     * @param bool $keyPoint 重
     * @param bool $isReticent
     * @return array[]
     */
    public static function getOrderTags(
        int $platform = 0,
        bool $locationStatus = false,
        bool $changeContract = false,
        bool $removeContract = false,
        bool $isAbnormal = false,
        bool $isConfirm = false,
        bool $isDuoShop = false,
        bool $isQuit = false,
        bool $isReticent = false,
        bool $keyPoint = false
    ): array {
        switch ($platform) {
            case 0:
                return [
                    [
                        'name'   => '迁',
                        'status' => $locationStatus,
                        'text'   => '迁址店',
                        'style'  => 'color: #fff;background-color: rgb(253, 0, 62);border:none',
                        'type'   => 'location' // 迁址类型
                    ],
                    [
                        'name'   => '合同变更',
                        'status' => $changeContract, // @青叶 返回 合同是否变更
                        'text'   => '合同变更中',
                        'style'  => 'color: #fff;background-color: rgb(253, 0, 62);border:none',
                        'type'   => 'changeContract' // 迁址类型
                    ],
                    [
                        'name'   => '解',
                        'status' => $removeContract,
                        'text'   => '解除协议签署中',
                        'style'  => 'color: #fff;background-color: rgb(253, 0, 62);border:none',
                        'type'   => 'location' // 迁址类型
                    ],
                    [
                        'name'   => '沉',
                        'status' => $isReticent,
                        'text'   => '沉默客户状态',
                        'style'  => 'color: #fff;background-color: rgb(253, 0, 62);border:none',
                        'type'   => 'isReticent' // 选址标签-沉默客户状态
                    ],
                ];
            case 1:
                return [
                    [
                        'name'   => '迁',
                        'status' => $locationStatus,
                        'text'   => '',
                        'style'  => 'color: #fff;background-color: rgb(253, 0, 62);border:none',
                        'type'   => 'location' // 迁址类型
                    ],
                    [
                        'name'   => '合同变更',
                        'status' => $changeContract, // @青叶 返回 合同是否变更
                        'text'   => '',
                        'style'  => 'color: #fff;background-color: rgb(253, 0, 62);border:none',
                        'type'   => 'changeContract' // 迁址类型
                    ],
                    [
                        'name'   => '解',
                        'status' => $removeContract,
                        'text'   => '',
                        'style'  => 'color: #fff;background-color: rgb(253, 0, 62);border:none',
                        'type'   => 'location' // 迁址类型
                    ],
                    [
                        'name'   => '异',
                        'status' => $isAbnormal,
                        'text'   => '',
                        'style'  => 'color: #fff;background-color: rgb(253, 0, 62);border:none',
                        'type'   => 'abnormal' // 迁址类型
                    ],
                    [
                        'name'   => '合',
                        'status' => $isConfirm,
                        'text'   => '',
                        'style'  => 'color: #fff;background-color: rgb(253, 0, 62);border:none',
                        'type'   => 'confirm' // 迁址类型
                    ],
                    [
                        'name'   => '多',
                        'status' => $isDuoShop,
                        'text'   => '',
                        'style'  => 'color: #fff;background-color: rgb(253, 0, 62);border:none',
                        'type'   => 'duoShop' // 迁址类型
                    ],
                    [
                        'name'   => '离',
                        'status' => $isQuit,
                        'text'   => '',
                        'style'  => 'color: #fff;background-color: rgb(253, 0, 62);border:none',
                        'type'   => 'isQuit' // 迁址类型
                    ],
                    [
                        'name'   => '重',
                        'status' => $keyPoint,
                        'text'   => '',
                        'style'  => 'color: #fff;background-color: rgb(253, 0, 62);border:none',
                        'type'   => 'keyPoint' // 迁址类型
                    ]
                ];
            default:
                return [];
        }

    }

    public static function getDifferentV2(array $orderPermissionList)
    {
        $lists = OpenShopMainProcessModel::query()
                                         ->join('open_shop_sign_order as order', 'order.mainProcessId', '=',
                                             'open_shop_main_process.id')
                                         ->where('order.status', '!=', SignOrderEnum::ORDER_STATUS_NO)
                                         ->when(!$orderPermissionList['isAll'],
                                             function ($query) use ($orderPermissionList) {
                                                 $query->whereRaw("open_shop_main_process." . $orderPermissionList['rawSql']);
                                             })
                                         ->select("nowStepStatus", DB::raw("count(*) as ct"))
                                         ->groupBy('nowStepStatus')
                                         ->get()
                                         ->keyBy('nowStepStatus');

        $frame = [
            [
                'title' => '商家签约',
                'value' =>
                    [
                        [
                            'name'          => '商家待支付',
                            'stepStatusStr' => MissionTemplateEnum::STEP_STATUS_1,
                        ],
                        [
                            'name'          => '商家待签约',
                            'stepStatusStr' => MissionTemplateEnum::STEP_STATUS_2,
                        ],
//                        [
//                            'name'          => '披露单待上传',
//                            'stepStatusStr' => MissionTemplateEnum::STEP_STATUS_101,
//                            'count'         => OpenShopSignOrderModel::countDisclosure($orderPermissionList),
//                        ]
                    ],
            ],

            [
                'title' => '开发选址',
                'value' => [

                    [
                        'name'          => '开发待指派',
                        'stepStatusStr' => MissionTemplateEnum::STEP_STATUS_3,
                    ],
                    [
                        'name'          => '选址待提交',
                        'stepStatusStr' => MissionTemplateEnum::STEP_STATUS_4,
                    ],
                    [
                        'name'          => '商家待确认',
                        'stepStatusStr' => MissionTemplateEnum::STEP_STATUS_5,
                    ],
                ]
            ],
            [
                'title' => '空间设计',
                'value' =>
                    [

                        [
                            'name'          => '建店信息待确认',
                            'stepStatusStr' => MissionTemplateEnum::STEP_STATUS_6,
                        ],
                        [
                            'name'          => '设计师待指派',
                            'stepStatusStr' => MissionTemplateEnum::STEP_STATUS_7,
                        ],
                        [
                            'name'          => '设计模块待确认',
                            'stepStatusStr' => MissionTemplateEnum::STEP_STATUS_13,
                        ],
                        [
                            'name'          => '设计模块待支付',
                            'stepStatusStr' => MissionTemplateEnum::STEP_STATUS_14,
                        ],
                        [
                            'name'          => '设备模块待确认',
                            'stepStatusStr' => MissionTemplateEnum::STEP_STATUS_15,
                        ],
                        [
                            'name'          => '设备模块待支付',
                            'stepStatusStr' => MissionTemplateEnum::STEP_STATUS_16,
                        ],
                        [
                            'name'          => '整套图待提交',
                            'stepStatusStr' => MissionTemplateEnum::STEP_STATUS_8,
                        ],
                        [
                            'name'          => '软装模块待支付',
                            'stepStatusStr' => MissionTemplateEnum::STEP_STATUS_17,
                        ],
                    ],
            ],
            [
                'title' => '工程营建',
                'value' =>
                    [
                        [
                            'name'          => '进场待确认',
                            'stepStatusStr' => MissionTemplateEnum::STEP_STATUS_9,
                        ],
                        [
                            'name'          => '施工待完成',
                            'stepStatusStr' => MissionTemplateEnum::STEP_STATUS_10,
                        ],
                    ],
            ],
//            [
//                'title' => '门店验收',
//                'value' =>
//                    [
//                        [
//                            'name'          => '督导待指派',
//                            'stepStatusStr' => MissionTemplateEnum::STEP_STATUS_11,
//                        ],
//                        [
//                            'name'          => '督导待验收',
//                            'stepStatusStr' => MissionTemplateEnum::STEP_STATUS_12,
//                        ],
//                    ],
//            ],
            [
                'title' => '正式开业',
                'value' =>
                    [
                        [
                            'name'          => '开业报告待提交',
                            'stepStatusStr' => MissionTemplateEnum::STEP_STATUS_18,
                        ],
                        [
                            'name'          => '装修保证金待退',
                            'stepStatusStr' => MissionTemplateEnum::STEP_STATUS_100,
                            'count'         => OpenShopUserContractModel::getRefundDecorationDepositOrderCount($orderPermissionList['rawSql']),
                        ],
                    ],
            ],
        ];

        foreach ($frame as &$mainStep) {
            foreach ($mainStep['value'] as &$step) {
                if (!isset($step['count']) || $step['count'] == 0) {
                    $step['count'] = $lists[$step['stepStatusStr']]['ct'] ?? 0;
                }
            }
        }

        return $frame;
    }

    /**
     * 关闭订单业务逻辑
     * @param OpenShopSignOrderModel $order
     * @param int $type 1-自动关闭，2-手动关闭
     * @param int $uid 0为系统
     * @return void
     */
    public static function close(OpenShopSignOrderModel $order, int $type, int $uid = 0)
    {
        if (SignOrderEnum::PAY_STATUS_NULL === $order->payStatus) {
            $order->status = SignOrderEnum::ORDER_STATUS_NO;
            $order->save();
            Log::info("签约订单:{$order->id} 自动关闭已关闭");
            event(new OrderClosedEvent($order, $type, $uid));
        }
    }


    /**
     * 获取支付记录
     *
     * @param $orderNo
     * @return array
     * @throws Exception
     */
    public static function orderPayHistory($orderNo): array
    {
        try {
            return [
                "orderPayHistory" => OrderPayHistoryResource::collection(
                    OpenShopSignOrderPayHistoryModel::query()
                                                    ->where("orderNo", $orderNo)
                                                    ->where('payStatus',
                                                        OpenShopSignOrderPayHistoryModel::PAY_STATUS_OK)
                                                    ->orderByDesc('id')
                                                    ->get()
                ),
                'orderRefundList' => self::getRefundList($orderNo),
                'isMainOrder'     => MainProcessService::getIsPidOrder($orderNo)
            ];
        } catch (Exception $exception) {
            handleException($exception);
        }
        return [];
    }


    public static function getRefundList($orderNo)
    {
        $list = OpenShopPreparationOrderRefundModel::query()
                                                   ->where('orderNo', $orderNo)
                                                   ->where('status',
                                                       OpenShopPreparationOrderRefundModel::ORDER_STATUS_1)
                                                   ->orderByDesc('id')
                                                   ->get()->toArray();
        if (empty($list)) {
            return [];
        }
        $uids         = array_column($list, 'createdByUid');
        $userInfoList = RmsUserService::getRmsUserInfoByUserIds($uids);
        $userInfoList = array_column($userInfoList['data'], null, 'id');
        foreach ($list as &$item) {
            if (isset($userInfoList[$item['createdByUid']])) {
                $item['createdByName'] = $userInfoList[$item['createdByUid']]['username'];
            }
        }
        return $list;
    }


    //根据订单获得开店阶段状态
    public static function getStepByOrderNo($orderNo)
    {
        //先看Location
        $stepText = '';
        $step     = (string)OpenShopLocationModel::query()
                                                 ->where('orderNo', $orderNo)
                                                 ->value('step');
        foreach (UserOrderEnum::STEP_LOCATION_MAPPING_1 as $k => $item) {
            if (in_array($step, $item)) {
                if ($step == MainProcessEnum::SHOP_LOCATION_CONFIRM) {
                    $stepText = UserOrderEnum::OPEN_SHOP_STATUS_MAPPING[$k];
                    break;
                }
                $stepText = UserOrderEnum::STEP_FORMAT_FOREFRONT[$k] ?? UserOrderEnum::OPEN_SHOP_STATUS_MAPPING[$k];
                break;
            }
        }
        if (!mb_strlen($step)) {
            $step = (string)OpenShopSignOrderModel::query()
                                                  ->where('orderNo', $orderNo)
                                                  ->value('step');
            foreach (UserOrderEnum::STEP_LOCATION_MAPPING_2 as $k => $item) {
                if (in_array($step, $item)) {
                    $stepText = UserOrderEnum::STEP_FORMAT_FOREFRONT[$k];
                    break;
                }
            }
        }
        return $stepText;
    }

    /**
     * 提交线下支付订单
     *
     * @param object $rmsUser
     * @param string $orderNo
     * @param array $params
     * @throws Exception
     */
    public static function submitOrderProof(object $rmsUser, string $orderNo, array $params, bool $needLog = true)
    {
        // TODO 如果支持其他sysType，需要改造sysType,bizId

        try {
            $orderDetail = OpenShopSignOrderModel::query()->where("orderNo", $orderNo)->first();
            $payHistory  = OpenShopSignOrderPayHistoryModel::query()
                                                           ->where("orderNo", $orderNo)
                                                           ->where("payStatus",
                                                               OpenShopSignOrderPayHistoryModel::PAY_STATUS_OK)
                                                           ->get();

            $collectProof   = collect($params["proof"]);
            $proofPayPrice  = $collectProof->sum("price");
            $hasPay         = $proofPayPrice + $payHistory->sum("payPrice");
            $remainPayPrice = $orderDetail->shouldPayPrice - $hasPay;
            if ($remainPayPrice < 0) {
                throw new ResponseHttpException(\App\Enums\BaseErrorCode::$PAY_AMOUNT_GT_SHOULD_PAY);
            }

            // 备注: 姓名 + 加盟费
            $userName = (string)optional($orderDetail->identityCardRel)->name;
            $subject  = $userName . '-' . RmsPayEnum::SYS_TYPE_TEXT[CheckEnum::SYS_TYPE_OPEN_SHOP_LEAGUE];
            if ($orderDetail->orderType == SignOrderEnum::ORDER_TYPE_IMPORT) {
                $subject .= "（历史订单导入）";
            }
            $flowNumbers        = $collectProof->pluck('flowNumber')->reject(function ($v) {
                return empty($v);
            })->toArray();
            $flowNumbersCollect = collect();
            // 确认银行流水和已选择的数量一致
            if (count($flowNumbers)) {
                $flowNumbersCollect = CheckCmbBankFlow::query()
                                                      ->whereIn('refnbr', $flowNumbers)
                                                      ->where('used', 0)
                                                      ->get();
                if ($flowNumbersCollect->count() != count($flowNumbers)) {
                    throw new ResponseHttpException(\App\Enums\BaseErrorCode::$PAY_OFFLINE_FLOW_MISMATCH);
                }
            }

            $count              = $collectProof->count();
            $flowNumbersCollect = collect();

            try {

                DB::beginTransaction();

                $collectProof->each(function ($item, $key) use (
                    $orderNo,
                    $count,
                    $remainPayPrice,
                    $orderDetail,
                    $rmsUser,
                    $subject,
                    $flowNumbersCollect,
                    $needLog
                ) {
                    if ($needLog) {
                        ChangeSupport::getInstance()->buildInsertChanges(
                            "上传支付凭证",
                            [
                                "proofImg" => getPrivateFileKey($item["img"]),
                                "price"    => $item["price"]
                            ],
                            OpenShopSignOrderPayHistoryModel::$orderLogTranslateConfig
                        );
                    }
                    $payNo = $item['flowNumber'] ?? '';
                    if (in_array($item["payChannel"], [OpenShopSignOrderPayHistoryModel::PAY_CHANNEL_ALI, OpenShopSignOrderPayHistoryModel::PAY_CHANNEL_WX])) {
                        $payNo = '线下二维码支付，无流水';
                    }
                    $item = [
                        "orderNo"        => $orderNo,
                        "payNo"          => $payNo,
                        "shouldPayPrice" => $item["price"],
                        "payPrice"       => $item["price"],
                        "payStatus"      => ($count == $key + 1 && $remainPayPrice == 0) ? OpenShopSignOrderPayHistoryModel::PAY_STATUS_WAIT : OpenShopSignOrderPayHistoryModel::PAY_STATUS_OK,
                        "payChannel"     => $item["payChannel"],
                        "type"           => OpenShopSignOrderPayHistoryModel::TYPE_FINAL,
                        "subject"        => $subject,
                        "proofImg"       => ltrim((string)parse_url($item["img"], PHP_URL_PATH), '/'),
                        "createdAt"      => time(),
                        "updatedAt"      => time(),
                        "payTime"        => $flowNumbersCollect->count() ? strtotime($flowNumbersCollect->last()->etyDateTime) : time(),
                        'sysType'        => CheckEnum::SYS_TYPE_OPEN_SHOP_LEAGUE,
                        'bizId'          => $orderNo,
                    ];

                    $payId = OpenShopSignOrderPayHistoryModel::query()->insertGetId($item);
                    (new SignOrderService($item['orderNo']))->paySuccess($payId, $item["payPrice"]);
                });

                //todo 订单日志写入
                ChangeSupport::getInstance()->batchChangesWriteToOrderLog(
                    $orderDetail->id,
                    OpenShopSignOrderLogModel::UPLOAD_ORDER_PAY_PROOF,
                    $rmsUser->username ?? '',
                    $rmsUser->id ?? 0
                );
                if (count($flowNumbers)) {
                    // 把已经用的了招商流水设置成已使用
                    CheckCmbBankFlow::query()
                        ->whereIn('refnbr', $flowNumbers)
                        ->update(['used' => 1]);
                }

                DB::commit();
            } catch (Exception $exception) {
                DB::rollBack();
                throw $exception;
            }
        } catch (Exception $exception) {
            handleException($exception, \App\Enums\BaseErrorCode::$PAY_OFFLINE_FAIL, ["orderNo" => $orderNo]);
        }
    }

    public static function queryAvailableFlows(
        string $date,
        int $amount,
        string $name = '',
        string $account = '',
        int $pageNum = 1,
        int $pageSize = 10
    ) {
        // 如果是查今天的流水，则自动刷新一下数据
        if ($date == date('Y-m-d')) {
            CmbAccountService::syncIncomeFlows($date);
        }
        $paginator = CheckCmbBankFlow::query()
                                     ->where('etydat', $date)
                                     ->where('trsamt', $amount / 100)
                                     ->when(strlen($name), function ($query) use ($name) {
                                         $query->where('rpynam', 'like', "%{$name}%");
                                     })
                                     ->when(strlen($account), function ($query) use ($account) {
                                         $query->where('rpyacc', 'like', "%{$account}%");
                                     })
                                     ->where('used', 0)
                                     ->orderBy('etyDateTime', 'desc')
                                     ->paginate($pageSize, ['*'], 'pageNum', $pageNum);
        return [
            'count'    => $paginator->total(),
            'pageNum'  => $pageNum,
            'pageSize' => 10,
            'list'     => $paginator->map(function (CheckCmbBankFlow $flow) {
                $account = $flow->rpyacc;
                if (mb_strlen($account) <= 8) {
                    $account = '***' . mb_substr($account, 3);
                } else {
                    if (mb_strlen($account) <= 12) {
                        $account = mb_substr($account, 0, 5) . '****' . mb_substr($account, 9);
                    } else {
                        $account = mb_substr($account, 0, 6) . '****' . mb_substr($account, 10);
                    }
                }
                return [
                    'outAccount' => $account,
                    'time'       => $flow->etyDateTime,
                    'flowNumber' => $flow->refnbr,
                    'name'       => $flow->rpynam,
                    'bankName'   => $flow->rpybnk,
                    'amount'     => round(100 * $flow->trsamt),
                    'channel'    => '银行转账',
                    'inAccount'  => '110939648910401', // 厦门心有炸念餐饮管理有限公司 招商银行卡
                ];
            }),
        ];
    }


    /**
     * 更新订单的操作人等信息
     *
     * @param string $orderNo
     */
    public static function updateOrderPermissionAnchor(string $orderNo)
    {
        // 判断是否存在
        $order = OpenShopSignOrderModel::query()
                                       ->with('baseInfoRel') // 创建订单
                                       ->with('shopLocationRel') // 选址
                                       ->with('spaceDesignRel') // 空间设计
                                       ->with('checkAcceptRel') // 工程验收
                                       ->with('siteMissionsRel') // 任务处理
                                       ->where('orderNo', $orderNo)
                                       ->first();

        $provinceCode = (optional($order->baseInfoRel)->chooseShopProvinceCode) ?: 0;
        if (!empty($order->shopLocationRel) && !empty($order->shopLocationRel->provinceCode)) {
            $provinceCode = $order->shopLocationRel->provinceCode;
        }

        $updateData = [
            'signInvestmentManagerId'  => $order->investmentManagerId ?: 0,
            'localInvestmentManagerId' => (optional($order->shopLocationRel)->investmentManagerId) ?: 0,
            'provinceCode'             => $provinceCode,
            'cityCode'                 => (optional($order->baseInfoRel)->chooseShopCityCode) ?: 0,
            'districtCode'             => (optional($order->baseInfoRel)->chooseShopDistrictCode) ?: 0,
            'designUid'                => (optional($order->spaceDesignRel)->designUid) ?: 0,
            'preparationUid'           => (optional($order->spaceDesignRel)->preparationUid) ?: 0,
            'checkManagerId'           => (optional($order->checkAcceptRel)->managerId) ?: 0,
            'orderStatus'              => $order->status,
        ];

        foreach ($order->siteMissionsRel as $mission) {
            switch ($mission->stepStatus) {
                case MissionTemplateEnum::STEP_STATUS_3:
                    $updateData['localInvestmentHandleUserId'] = $mission->dealUid;
                    break;
                case MissionTemplateEnum::STEP_STATUS_7:
                    $updateData['designUidHandleUserId'] = $mission->dealUid;
                    break;
                case MissionTemplateEnum::STEP_STATUS_11:
                    $updateData['checkManagerHandleUserId'] = $mission->dealUid;
                    break;
            }
        }

        OpenShopSignOrderPermissionAnchorModel::updateOrCreate(
            ['orderNo' => $orderNo],
            $updateData
        );

    }


    /**
     * 更新订单的标签
     *
     * @param string $orderNo
     */
    public static function updateOrderTags(string $orderNo)
    {
        $orderInfo = OpenShopSignOrderModel::query()
                                           ->where('orderNo', $orderNo)
                                           ->with('spaceDesignRel') // 空间设计
                                           ->with('tagsMappingRel')
                                           ->first();



        // 筹备标签

    }

    /**
     * 更换经理
     *
     * @param object $rmsUser
     * @param object $params
     * @param int $from 1 tiger 2 rms
     * @param bool $validOriginalManager true强制校验原经理是否存在
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public static function changeManager(
        object $rmsUser,
        object $params,
        int $from = 1,
        bool $validOriginalManager = false
    ) {
        if (!empty($params->mainProcessId)) {
            $mainProcessId = $params->mainProcessId;
        } else {
            $mainProcessId = OpenShopOrderManagerModel::query()->where("id", $params->id)->first()->mainProcessId;
        }

        $originalManager = OpenShopOrderManagerModel::query()
                                                    ->where("mainProcessId", $mainProcessId)
                                                    ->where("type", $params->type)
                                                    ->orderByDesc("id")
                                                    ->first();

        // 原经理不存在
        if ($validOriginalManager && !$originalManager) {
            return false;
        }

        // 原经理Uid
        $oriMangerUid = OpenShopOrderManagerModel::getManagerUid($mainProcessId, $params->type);

        if ($oriMangerUid == $params->managerId) {
            return false;
        }

        $signOrder = OpenShopSignOrderModel::query()->where("mainProcessId", $mainProcessId)->first();
        if ($signOrder == null) {
            return false;
        }
        $shopId = $params->shopId ?? 0;
        if (!$shopId) {
            $shopId = (int)OpenShopMainProcessModel::query()->where('id', $mainProcessId)->value('shopId');
        }

        DB::beginTransaction();

        OpenShopOrderManagerModel::generateManagerOrUpdate(
            $params->type,
            $mainProcessId,
            $params->managerId,
            $params->managerName,
            OpenShopOrderManagerModel::ORDER_STATUS_NORMAL,
            $shopId
        );

        $commonUpdate = ["updatedAt" => time(), "updatedByUid" => $rmsUser->id];
        switch ($params->type) {
            case OpenShopOrderManagerModel::MANAGER_TYPE_1:
                OpenShopSignOrderModel::query()
                                      ->where("mainProcessId", $mainProcessId)
                                      ->update(array_merge($commonUpdate, [
                                          "investmentManagerName" => $params->managerName,
                                          "investmentManagerId"   => $params->managerId
                                      ]));
                break;
            case OpenShopOrderManagerModel::MANAGER_TYPE_2:
                OpenShopLocationModel::query()
                                     ->where("mainProcessId", $mainProcessId)
                                     ->update(array_merge($commonUpdate, [
                                         "investmentManagerName" => $params->managerName,
                                         "investmentManagerId"   => $params->managerId
                                     ]));
                OpenShopSiteLocationModel::shopLocationManagerInitOrUpdate(
                    $signOrder->orderNo, $params->managerName, $params->managerId, $mainProcessId, $rmsUser->id
                );

                //更新处理人
                OpenShopSiteMissionModel::query()
                                        ->where('orderNo', $signOrder->orderNo)
                                        ->whereIn('stepStatus',
                                            [MissionTemplateEnum::STEP_STATUS_4, MissionTemplateEnum::STEP_STATUS_5])
                                        ->update([
                                            'dealUid' => $params->managerId
                                        ]);
                break;
            case OpenShopOrderManagerModel::MANAGER_TYPE_3:
                OpenShopSpaceDesignModel::query()
                                        ->where("mainProcessId", $mainProcessId)
                                        ->update(array_merge($commonUpdate, [
                                            "designName" => $params->managerName,
                                            "designUid"  => $params->managerId
                                        ]));
                break;
            case OpenShopOrderManagerModel::MANAGER_TYPE_4:
                OpenShopSpaceDesignModel::query()
                                        ->where("mainProcessId", $mainProcessId)
                                        ->update(array_merge($commonUpdate, [
                                            "preparationName" => $params->managerName,
                                            "preparationUid"  => $params->managerId
                                        ]));

                //更新处理人
//                OpenShopSiteMissionModel::query()
//                    ->where('orderNo', $signOrder->orderNo)
//                    ->whereIn('stepStatus', [MissionTemplateEnum::STEP_STATUS_14, MissionTemplateEnum::STEP_STATUS_16, MissionTemplateEnum::STEP_STATUS_17])
//                    ->update([
//                        'dealUid' => $params->managerId
//                    ]);

                break;
            case OpenShopOrderManagerModel::MANAGER_TYPE_5:
                OpenShopCheckAcceptModel::query()
                                        ->where("mainProcessId", $mainProcessId)
                                        ->update(array_merge($commonUpdate, [
                                            "managerName" => $params->managerName,
                                            "managerId"   => $params->managerId
                                        ]));
                break;
        }

        //TODO 订单日志写入
        $newChanges = [
            "theme"      => vsprintf("%s %s", [
                OpenShopOrderManagerModel::TYPE_MAP[$params->type],
                "变更"
            ]),
            "changeType" => ChangeSupport::CHANGE_TYPE_SINGLE_UPDATE,
            "data"       => [
                [
                    "key"         => "managerName",
                    "beforeValue" => $originalManager->managerName,
                    "afterValue"  => $params->managerName,
                    "beforeText"  => $originalManager->managerName,
                    "afterText"   => $params->managerName,
                    "type"        => ChangeSupport::FILED_TYPE_STRING,
                    "description" => "顾问名称"
                ],
                [
                    "key"         => "managerId",
                    "beforeValue" => $originalManager->managerUid,
                    "afterValue"  => $params->managerId,
                    "beforeText"  => $originalManager->managerUid,
                    "afterText"   => $params->managerId,
                    "type"        => ChangeSupport::FILED_TYPE_STRING,
                    "description" => "顾问ID"
                ],
            ]
        ];

        ChangeSupport::getInstance()->pushChanges($newChanges);
        ChangeSupport::getInstance()->batchChangesWriteToOrderLog(
            $signOrder->id,
            OpenShopSignOrderLogModel::UPDATE_MANAGER,
            $rmsUser->username,
            $rmsUser->id
        );

        if ($oriMangerUid) {

            // 任务处理人变更
            $handlerRole = MissionTemplateEnum::MANAGER_TYPE_TO_HANDLER_ROLE[$params->type] ?? 0;
            OpenShopSiteMissionModel::changeManagerUid($signOrder->orderNo, $params->managerId, $handlerRole);

            // 删除通知
            OpenShopProcessDetailNoticeEmployeeModel::replaceUid($signOrder->orderNo, $oriMangerUid, $params->managerId);

            // 审批流程处理人变更
//            $shopId = (int)OpenShopMainProcessModel::query()->where('id', $mainProcessId)->value('shopId');
            $workflowHandlerType = WorkflowEnum::OPEN_SHOP_MANAGER_TYPE_TO_HANDLER_TYPE[$params->type] ?? -1;
            WorkflowHandlerUserService::changeNodeHandlerUid([$shopId], $workflowHandlerType, $params->managerId, $params->managerName);
        }

        DB::commit();

        try {
            if ($from == 1) {
                switch ($params->type) {
                    case OpenShopOrderManagerModel::MANAGER_TYPE_5:
                        ShopService::updateShopCouncilorId($signOrder->orderNo, $params->managerId);
                        break;
                }
            }
        } catch (\Exception $e) {
            Log::warning($e);
        }

        // 订单权限变更
        self::updateOrderPermissionAnchor($signOrder->orderNo);

        return true;
    }


    public static function changeManagerInternal($shopCode, $type, $uid, $uname)
    {
        $signOrder = OpenShopSignOrderModel::query()
                                           ->where('shopCode', $shopCode)
                                           ->whereIn('status',
                                               [SignOrderEnum::ORDER_STATUS_OK, SignOrderEnum::ORDER_STATUS_COMPLETE])
                                           ->first();

        if (empty($signOrder)) {
            return [];
        }

        $params = [
            'type'          => $type,
            'managerId'     => $uid,
            'managerName'   => $uname,
            'mainProcessId' => $signOrder->mainProcessId
        ];

        OrderService::changeManager(getRmsUserInfoByAuth(), (object)$params, 2);
        return $params;
    }

    /**
     * @param string $orderNo
     * @return array|void
     * @throws Exception|GuzzleException
     */
    public static function getOrderCityFee(string $orderNo)
    {
        try {
            $shopLocation = OpenShopLocationModel::query()->where("orderNo", $orderNo)->first();
            return [
                "cityGradeFee" => self::getOrderFeeFunc($shopLocation->cityCode)
            ];
        } catch (Exception $exception) {
            handleException($exception);
        }
    }

    /**
     * 获取城市分级金额
     *
     * @param string $cityCode
     * @return mixed|string
     * @throws GuzzleException
     */
    public static function getOrderFeeFunc(string $cityCode)
    {
        // 获取 指定城市的金额
        $cityGradeAssignFee = ConfigService::config("openShop")['cityGradeAssignFee'];

        if (key_exists($cityCode, $cityGradeAssignFee)) {
            return $cityGradeAssignFee[$cityCode];
        }

        $cityGradeFee  = ConfigService::config("openShop")["cityGradeFee"];
        $cityGradeInfo = RmsAreaRemote::getCityGrade($cityCode)["cityInfo"];

        if (empty($cityGradeInfo) || empty($cityGrade = collect($cityGradeFee)->where("grade", $cityGradeInfo["grade"])
                                                                              ->first())) {
            $gradeMoney = end($cityGradeFee)["fee"];
        } else {
            $gradeMoney = $cityGrade["fee"];
        }
        return $gradeMoney;
    }

    /**
     * 复制原订单
     *
     * @param string $orgOrderNo
     */
    public function copyNewOrder(string $orgOrderNo)
    {
        $orderDetail = OpenShopSignOrderModel::orderDetail(
            $orgOrderNo,
            true,
            true,
            true
        )->getIterator()->current();

        // 创建原订单数据
        $this->step0($orderDetail);
    }


    /**
     * 创建订单
     *
     * @param $orderDetail
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function step0($orderDetail)
    {

        $userIdentityCardInfo = $orderDetail->identityCardRel->toArray();
        unset($userIdentityCardInfo['id']);
        unset($userIdentityCardInfo['mainProcessPid']);
        unset($userIdentityCardInfo['laravel_through_key']);

        $userBaseInfo = $orderDetail->baseInfoRel->toArray();
        unset($userBaseInfo['id']);
        unset($userBaseInfo['orderNo']);
        unset($userBaseInfo['mainProcessPid']);
        unset($userBaseInfo['area']);
        unset($userBaseInfo['province']);
        unset($userBaseInfo['city']);
        unset($userBaseInfo['district']);
        unset($userBaseInfo['leasingManager']);
        unset($userBaseInfo['sourceText']);

        $userExperience = [];

        $userMainProcessInfo = [
            'shopId'             => $orderDetail->mainProcessRel->shopId,
            'childLocationOrder' => 1,
            'locationPid'        => $orderDetail->mainProcessRel->id,
//            'pid'                => $orderDetail->mainProcessRel->pid,
//            'childOrder'         => $orderDetail->mainProcessRel->childOrder
        ];

        $userSignOrderInfo = [
            'shopCode' => $orderDetail->shopCode
        ];

        $signOrderInfo = UserBaseInfoService::insert(getRmsUserInfoByAuth(), $userIdentityCardInfo, $userBaseInfo,
            $userExperience, $userMainProcessInfo, $userSignOrderInfo);

        $contractRelInfo = $orderDetail->contractRel->toArray();

        $contractRelInfo['orderNo'] = $signOrderInfo['orderNo'];
        unset($contractRelInfo['id']);

        UserContractService::insert(getRmsUserInfoByAuth(), $contractRelInfo, false, false);

        $orderInfo = OpenShopSignOrderModel::query()->where('orderNo', $signOrderInfo['orderNo'])->first();

        //修改签约订单表状态, 以及各种信息
        OpenShopSignOrderModel::query()
                              ->where('orderNo', $signOrderInfo['orderNo'])
                              ->update([
                                  'step'                  => SignOrderEnum::STEP_5,
                                  'signTime'              => time(),
                                  'shouldPayPrice'        => 0,
                                  'payStatus'             => 2,
                                  "investmentManagerName" => $orderDetail->investmentManagerName,
                                  "investmentManagerId"   => $orderDetail->investmentManagerId
                              ]);

        //经理表写入筹备数据
        OpenShopOrderManagerModel::generateManagerOrUpdate(
            OpenShopOrderManagerModel::MANAGER_TYPE_1,
            $orderInfo->mainProcessId,
            $orderDetail->investmentManagerId,
            $orderDetail->investmentManagerName
        );

        $siteLocationRel = $orderDetail->siteLocationRel;

        // 获取开发顾问
        $developConsultantId   = $siteLocationRel->developConsultantId ?? 0;
        $developConsultantName = $siteLocationRel->developConsultantName ?? '';

        // 判断是否选址已经离职
        $userInfo = current((new RmsUserApi())->getFsUsers('', ['rmsUserId', 'isExited'], '',
                $developConsultantId)['data']['lists'] ?? []);

        $orderNoInfo = [
            'orderNo'       => $signOrderInfo['orderNo'],
            'mainProcessId' => $orderInfo->mainProcessId,
            'createdAt'     => time(),
            'updatedAt'     => time()
        ];

        if (empty($userInfo) || $userInfo['isExited']) {
            // 已经离职
            $stepStatus = MissionTemplateEnum::STEP_STATUS_3;

        } else {
            // 未离职
            $stepStatus = MissionTemplateEnum::STEP_STATUS_4;
            //
            $orderNoInfo['step'] = 1;

            //选址增加空记录
            OpenShopSiteLocationModel::shopLocationManagerInitOrUpdate($signOrderInfo['orderNo'],
                $developConsultantName,
                $developConsultantId,
                $orderInfo->mainProcessId,
                $developConsultantId,
                true
            );

            OpenShopOrderManagerModel::generateManagerOrUpdate(
                OpenShopOrderManagerModel::MANAGER_TYPE_2,
                $orderInfo->mainProcessId,
                $developConsultantId,
                $developConsultantName,
                $orderInfo->status
            );

            $orderNoInfo['investmentManagerId']   = $developConsultantId;
            $orderNoInfo['investmentManagerName'] = $developConsultantName;

            // 手动创建已完成的任务
            SiteMissionService::genMission($signOrderInfo['orderNo'], MissionTemplateEnum::STEP_STATUS_3,
                SiteMissionEnum::STATUS_2);
            //获取订单基础信息
            $userBaseInfoObj = OpenShopUserBaseInfoModel::getDataByOrderNo($signOrderInfo['orderNo']);
            //获取筹备uid
            $manager = OrganizationManageService::getOrganizationInfoByType(OrganizationManageEnum::TYPE_BRANCH_OFFICE,
                $userBaseInfoObj->chooseShopProvinceCode);

            if ($manager && $manager["preparationUid"] > 0) {
                //经理表写入筹备数据
                OpenShopOrderManagerModel::generateManagerOrUpdate(
                    OpenShopOrderManagerModel::MANAGER_TYPE_4,
                    $orderInfo->mainProcessId,
                    $manager["preparationUid"],
                    $manager["preparationName"]
                );
                //空间设计表写入
                OpenShopSpaceDesignModel::query()->updateOrCreate([
                    'orderNo' => $signOrderInfo['orderNo']
                ], [
                    "mainProcessId"   => $orderInfo->mainProcessId,
                    "createdAt"       => time(),
                    "preparationUid"  => $manager["preparationUid"],
                    "preparationName" => $manager["preparationName"]
                ]);
            } else {
                //空间设计表写入
                OpenShopSpaceDesignModel::query()->updateOrCreate([
                    'orderNo' => $signOrderInfo['orderNo']
                ], [
                    "mainProcessId"   => $orderInfo->mainProcessId,
                    "createdAt"       => time(),
                    "preparationUid"  => $developConsultantId,
                    "preparationName" => $developConsultantName
                ]);
            }
        }

        OpenShopLocationModel::query()->insert($orderNoInfo);

        // 更新主表的 step
        OpenShopMainProcessModel::query()->where('orderNo', $signOrderInfo['orderNo'])->update([
            'step' => 2
        ]);
        // 更新主表的当前nowStepStatus
        OpenShopMainProcessModel::updateNowStepStatus($signOrderInfo['orderNo'], $stepStatus);
        // 获取原表数据
        $orgMainInfo = OpenShopMainProcessModel::query()->where('orderNo', $orderDetail->orderNo)->first();

        OpenShopMainProcessModel::query()->where('orderNo', $signOrderInfo['orderNo'])->update([
            'startFeeTime' => $orgMainInfo->startFeeTime,
            'managePrice'  => $orgMainInfo->managePrice
        ]);

        // 创建任务
        SiteMissionService::genMission($signOrderInfo['orderNo'], $stepStatus);

        // 删除所有记录
        OpenShopSignOrderLogModel::query()->where('orderId', $orderInfo->id)->delete();

        if (empty($userInfo) || $userInfo['isExited']) {
            //  给省总推送任务
            NoticeService::signedJob($orderInfo, $developConsultantName);
        } else {
            // 给老选址推送消息
            NoticeService::assignManagerJob($orderInfo, $developConsultantName);
        }

        OrderService::updateOrderPermissionAnchor($orderInfo->orderNo);
    }


    /**
     * 获取作废类型
     *
     * @param string $orderNo
     * @return array|void
     * @throws Exception
     */
    public static function invalidOrderType(string $orderNo)
    {
        try {

            $signOrderModel = OpenShopSignOrderModel::getOrderDetailByOrderNo($orderNo);
            $invalidType    = self::getInvalidOrderType($signOrderModel);

            $invalidTypeFormClosure = function () use ($signOrderModel) {
                list($contractTypeKey, $contractType) = self::getInvalidContractType($signOrderModel);

                $jflxdz         = "北京市密云区经济开发区兴盛南路8号开发区办公楼501室-室-2631(经济开发区集中办公区)";
                $limitCloseDays = "(即)";
                $limitBackFiles = 15;
                $limitBackFee   = 7;
                $feeType_1      = "";
                $feeType_2      = "";
                $feeTypeVal_1   = "";
                $feeTypeVal_2   = "";

                switch ($contractTypeKey) {
                    case UserContractEnum::CONTRACT_TYPE_3_KEY:
                    case UserContractEnum::CONTRACT_TYPE_6_KEY:
                    case UserContractEnum::CONTRACT_TYPE_7_KEY:
                        $formContents = [
                            "yftxqsyf" => "",
                            "jflxdz"   => $jflxdz,//联系地址
                            "yfxm"     => $signOrderModel->identityCardRel->name,//乙方
                            "yfsfzh"   => $signOrderModel->identityCardRel->identityCardNumber,
                            "yflxdz"   => vsprintf(
                                "%s-%s",
                                [
                                    $signOrderModel->baseInfoRel->addressPrefix,
                                    $signOrderModel->baseInfoRel->address
                                ]
                            ),
                            "yflxfs"   => $signOrderModel->baseInfoRel->mobile,
                            "qysj"     => formatDateYmd(
                                $signOrderModel->contractRel->userExtContractRel->isNotEmpty() ? $signOrderModel->contractRel->userExtContractRel->getIterator()
                                                                                                                                                 ->current()->signTime : 0,
                                ""
                            ),
                            "htbh"     => $signOrderModel->contractRel->contractExtNo,
                            "yfsqdz"   => $signOrderModel->baseInfoRel->chooseShopAddressPrefix,
                            "jcsj"     => formatDateYmd(time()),
                            "jiri1"    => $limitCloseDays,
                            "jiri2"    => $limitBackFiles,
                            "jiri3"    => $limitBackFee,
                            "tqfy1"    => $feeType_1,
                            "tqfy2"    => $feeTypeVal_1,
                            "tqfy3"    => $feeType_2,
                            "tqfy4"    => $feeTypeVal_2,
                            "ycxfy1"   => (string)formatPrice($signOrderModel->contractRel->initialFee + $signOrderModel->contractRel->technologyTransferFee) / ($signOrderModel->contractRel->shopCount > 0 ? $signOrderModel->contractRel->shopCount : 1),
                            "ppsyf"    => "",
                            "jssqf"    => "",
                            "lybzhj"   => "",
                            "txqsyf1"  => "",
                            "yunfuwu1" => "",
                            "yfzhmc"   => $signOrderModel->baseInfoRel->cardAccountName,
                            "yfkhh"    => $signOrderModel->baseInfoRel->cardBankName,
                            "yfzh"     => $signOrderModel->baseInfoRel->cardNo,
                        ];
                        break;
                    case UserContractEnum::CONTRACT_TYPE_4_KEY:
                        $formContents = [
                            "yftxqsyf" => "",
                            "jflxdz"   => $jflxdz,//联系地址
                            "yfxm"     => $signOrderModel->identityCardRel->name,//乙方
                            "yfsfzh"   => $signOrderModel->identityCardRel->identityCardNumber,
                            "yflxdz"   => vsprintf(
                                "%s-%s",
                                [
                                    $signOrderModel->baseInfoRel->addressPrefix,
                                    $signOrderModel->baseInfoRel->address
                                ]
                            ),
                            "yflxfs"   => $signOrderModel->baseInfoRel->mobile,
                            "qysj"     => formatDateYmd(
                                $signOrderModel->contractRel->userExtContractRel->isNotEmpty() ? $signOrderModel->contractRel->userExtContractRel->getIterator()
                                                                                                                                                 ->current()->signTime : 0,
                                ""
                            ),
                            "htbh"     => $signOrderModel->contractRel->contractExtNo,
                            "yfsqdz"   => $signOrderModel->baseInfoRel->chooseShopAddressPrefix,
                            "jcsj"     => formatDateYmd(time()),
                            "jiri1"    => $limitCloseDays,
                            "jiri2"    => $limitBackFiles,
                            "jiri3"    => $limitBackFee,
                            "tqfy1"    => $feeType_1,
                            "tqfy2"    => $feeTypeVal_1,
                            "tqfy3"    => $feeType_2,
                            "tqfy4"    => $feeTypeVal_2,
                            "ycxfy1"   => (string)formatPrice($signOrderModel->contractRel->initialFee + $signOrderModel->contractRel->technologyTransferFee + $signOrderModel->contractRel->guidanceFee) / ($signOrderModel->contractRel->shopCount > 0 ? $signOrderModel->contractRel->shopCount : 1),
                            "ppsyf"    => "",
                            "jssqf"    => "",
                            "zxzfd1"   => "",
                            "lybzj"    => "",
                            "txqsyf1"  => "",
                            "yunfuwu1" => "",
                            "yfzhmc"   => $signOrderModel->baseInfoRel->cardAccountName,
                            "yfkhh"    => $signOrderModel->baseInfoRel->cardBankName,
                            "yfzh"     => $signOrderModel->baseInfoRel->cardNo,
                        ];
                        break;
                    case UserContractEnum::CONTRACT_TYPE_5_KEY:

                        $formContents = [
                            "yftxqsyf" => "",
                            "lxdz"   => $jflxdz,
                            "yfxm"   => $signOrderModel->identityCardRel->name,
                            "yfsfzh" => $signOrderModel->identityCardRel->identityCardNumber,
                            "yflxdz" => vsprintf(
                                "%s-%s",
                                [
                                    $signOrderModel->baseInfoRel->addressPrefix,
                                    $signOrderModel->baseInfoRel->address
                                ]
                            ),
                            "yflxfs" => $signOrderModel->baseInfoRel->mobile,
                            "qdrq"   => formatDateYmd(
                                $signOrderModel->contractRel->userExtContractRel->isNotEmpty() ? $signOrderModel->contractRel->userExtContractRel->getIterator()
                                                                                                                                                 ->current()->signTime : 0,
                                ""
                            ),
                            "htbh"   => $signOrderModel->contractRel->contractExtNo,
                            "sqdz"   => $signOrderModel->baseInfoRel->chooseShopAddressPrefix,
                            "qcrq"   => formatDateYmd(time()),
                            "jmf"    => (string)formatPrice($signOrderModel->contractRel->initialFee + $signOrderModel->contractRel->technologyTransferFee + $signOrderModel->contractRel->guidanceFee) / ($signOrderModel->contractRel->shopCount > 0 ? $signOrderModel->contractRel->shopCount : 1),
                            "ppsfy"  => "",
                            "jsjyf"  => "",
                            "zxzdf"  => "",
                            "txqsyf" => "",
                            "szhfy"  => "",
                            "lybzj"  => "",
                            "yfzhmc" => $signOrderModel->baseInfoRel->cardAccountName,
                            "yfkhh"  => $signOrderModel->baseInfoRel->cardBankName,
                            "yfzh"   => $signOrderModel->baseInfoRel->cardNo,
                        ];
                        break;
                    default:
                        throw new Exception("获取合同模板参数失败");
                        break;
                }
                return [$formContents, $contractType];
            };


            list($formContents, $contractType) = $invalidType > OpenShopSignOrderModel::INVALID_TYPE_2 ?
                $invalidTypeFormClosure() : [[], 0];

            return [
                "options"      => collect(OpenShopSignOrderModel::INVALID_TYPE_MAP)
                    ->map(function ($v, $k) use ($invalidType) {
                        return [
                            "text"     => $v,
                            "value"    => $k,
                            "selected" => $invalidType == $k
                        ];
                    })->values()->toArray(),
                "formContents" => $formContents,
                "contractType" => $contractType
            ];

        } catch (\Exception $exception) {
            handleException($exception);
        }
    }

    /**
     * @param OpenShopSignOrderModel $signOrder
     * @return int
     * @throws Exception
     */
    public static function getInvalidOrderType(OpenShopSignOrderModel $signOrder): int
    {
        switch ($signOrder->step) {
            case SignOrderEnum::STEP_1:
            case SignOrderEnum::STEP_2:
            case SignOrderEnum::STEP_3:
                //放弃支付 - 待支付或部分支付
                $invalidType = OpenShopSignOrderModel::INVALID_TYPE_1;
                break;
            case SignOrderEnum::STEP_4:
                //放弃签署 - 待签署
                $invalidType = OpenShopSignOrderModel::INVALID_TYPE_2;
                break;
            case SignOrderEnum::STEP_5:
                if ($signOrder->startBusinessRel && $signOrder->startBusinessRel->step == 1) {
                    //闭店 - 已开业
                    $invalidType = OpenShopSignOrderModel::INVALID_TYPE_4;
                } else {
                    //解约 - 已签署 开业报告待提交
                    $invalidType = OpenShopSignOrderModel::INVALID_TYPE_3;
                }
                break;
            default:
                throw new Exception("获取作废类型失败");
                break;
        }
        return $invalidType;
    }

    /**
     * 退款装修保证金
     *
     * @param string $orderNo
     * @throws ContainerExceptionInterface
     * @throws GuzzleException
     * @throws NotFoundExceptionInterface
     */
    public static function refundDecorationDeposit(string $orderNo)
    {
        try {
            logInfo("装修保证金执行退款", collect(["orderNo" => $orderNo]), true, false);
            $exists         = EkbApplyHistoryModel::query()->where(["orderNo" => $orderNo])->first();
            $signOrderModel = OpenShopSignOrderModel::query()->where("orderNo", $orderNo)->first();
            if ($exists || empty($signOrderModel) || $signOrderModel->mainProcessRel->locationPid > 0) {
                //[已存在 | 订单不存在 ｜ 迁址单] - 不继续执行
                return;
            }

            $userContract = $signOrderModel->contractRel;
            if ($userContract) {
                $decorationDeposit = $userContract->decorationDeposit;
                if ($decorationDeposit <= 0) {
                    return;
                }
                //校验是否内部加盟合同
                $noNeedRefundContractCategoryIds = ConfigService::getConfigDetail("openShop",
                        "refundDecorationDeposit")["value"]["noNeedRefundContractCategoryIds"] ?? [];
                $existsNoNeedCategory            = collect($userContract->toArray())->whereIn("categoryId",
                    $noNeedRefundContractCategoryIds)->count();
                if ($existsNoNeedCategory) {
                    return;
                }
            }

            $shopCount = OpenShopMainProcessModel::query()->where("pid", $signOrderModel->mainProcessRel->pid)->count();

            $fileSystem = getFileSystem();
            list($orderFormContent, $userContentArr) = CruiseOrderModel::getOrderFormContent($orderNo);
            $getFormContentValFunc = function (string $key, $default) use ($orderFormContent, $userContentArr) {
                $obj = $orderFormContent
                    ->where("field", $key)
                    ->first();
                return $obj ?
                    attributeGet($obj, "value", $default) :
                    attributeGet($userContentArr, $key, $default);
            };

            $handlePictureFieldsValFunc = function ($val) {
                $val = collect($val)->map(function($img){
                    return vsprintf("%s%s", [$img, "?x-oss-process=image/resize,p_30"]);
                })->toArray();
//                if (is_array($val) && count($val) > 2) {
//                    return array_slice($val, 0, 2);
//                }
                return $val;
            };

            $templateData = [
                "startBusinessActivity"            => $getFormContentValFunc("kai_ye_huo_dong_F9PPID", ""),
                "remainingProblems"                => $getFormContentValFunc("yi_liu_wen_ti_OMTOSo", ""),
                "solution"                         => $getFormContentValFunc("jie_jue_fang_an_cDBqNJ", ""),
                "hotOpeningPictures"               => $handlePictureFieldsValFunc($getFormContentValFunc("kai_ye_huo_bao_tu_pian_pERB1G",
                    [])),
                "growthConsultantIsInSite"         => $getFormContentValFunc("zeng_zhang_gu_wen_shi_fou_U0QBrU", ""),
                "growthConsultantWithShopPictures" => $handlePictureFieldsValFunc($getFormContentValFunc("zeng_zhang_gu_wen_he_men_fkc3R1",
                    [])),
                "shopDoorHeadPictures"             => $handlePictureFieldsValFunc($getFormContentValFunc("men_dian_men_tou_shi_jing_0aUgqm",
                    [])),
                "shopDoorInnerPictures"            => $handlePictureFieldsValFunc($getFormContentValFunc("men_dian_shi_nei_shi_jing_89LtUF",
                    [])),
                "shopNightDoorInnerPictures"       => $handlePictureFieldsValFunc($getFormContentValFunc("ye_jian_men_dian_shi_nei_ccQ3Uw",
                    [])),
            ];

            //获取申请人信息
            $supervisorUid = $signOrderModel->checkAcceptRel->managerId;
            if(empty($supervisorUid)){
                throw new Exception("易快报 - 【 {$orderNo} 】【 督导信息缺少配置 】");
            }
            //获取门店信息
            if (empty($shopInfo = RmsShopRemote::getShopFieldsByCodes([$signOrderModel->shopCode]))) {
                throw new Exception("易快报 - 【 {$orderNo} 】【 门店信息获取失败 】");
            }

            if (empty($supervisorUserInfo = RmsUserRemote::getRmsUserByIds([$supervisorUid]))) {
                throw new Exception("易快报 - 【 {$orderNo} 】【 督导信息获取失败 】");
            }

            //获取申请人飞书组织架构信息
            $fsUserList = RmsUserRemote::getFsUserListByIds([$supervisorUid]);
            if (empty($fsUserList) || empty($fsUserList["fsUserList"])) {
                throw new Exception("获取营运督导飞书组织架构信息失败 [userId : {$supervisorUid}]");
            }
            $fsUserDetail = current($fsUserList["fsUserList"]);
            //获取易快报申请部门信息
            $userDepartmentList = EKuaiBaoRemote::getDepartmentByName($fsUserDetail["departmentName"]);
            if (empty($userDepartmentList) || empty($userDepartmentList["items"])) {
                throw new Exception("【易快报】【根据用户获取申请部门信息失败】");
            }
            $userDepartmentId = $userDepartmentList["items"][0]["id"];


            $submitter = EKuaiBaoRemote::staff([$supervisorUserInfo[0]["mobile"]]);
            if (empty($submitter) || empty($submitter["items"])) {
                throw new Exception("易快报 - 【 {$orderNo} 】【 易快报未查询到督导信息 】");
            }

            $saveDir = getTmpDir("/pdf/" . formatDateYmd(time()));
            if (!$fileSystem->isDirectory($saveDir)) {
                $fileSystem->makeDirectory($saveDir, 0777, true);
            }

            $filePath = $saveDir . "/{$orderNo}.pdf";
            Pdf::loadView("pdf.content", $templateData)->save($filePath);

            //上传附件
            $attachment = EKuaiBaoRemote::attachmentUpload("{$orderNo}.pdf", $filePath)["value"];

            //创建收款账号
            $cardNo = $getFormContentValFunc("shou_kuan_xin_xi_EAHPE6", [])["cardNo"] ?? "";
            if (empty($cardNo)) {
                throw new Exception("易快报 - 【 {$orderNo} 】【 易快报未查询到当前单据收款信息 】");
            }
            $payeeInfoGroup = EKuaiBaoRemote::payeeInfos($cardNo);
            if ($payeeInfoGroup && !empty($payeeInfoGroup["items"])) {
                $payeeInfo   = current($payeeInfoGroup["items"]);
                $fullVisible = attributeGet($payeeInfo, "visibility.fullVisible", null);
                if (is_bool($fullVisible) && $fullVisible === false) {
                    EKuaiBaoRemote::updatePayeeInfos(
                        $payeeInfo["id"],
                        $payeeInfo["cardNo"],
                        $payeeInfo["name"],
                        $payeeInfo["branch"],
                        $payeeInfo["operatorId"]
                    );
                }
            } else {
                $payeeInfo = EKuaiBaoRemote::createPayeeInfos(
                    $getFormContentValFunc("shou_kuan_xin_xi_EAHPE6", [])["username"] ?? "",
                    $getFormContentValFunc("shou_kuan_xin_xi_EAHPE6", [])["bankName"] ?? "",
                    $getFormContentValFunc("shou_kuan_xin_xi_EAHPE6", [])["cardNo"] ?? "",
                    $submitter["items"][0]["id"],
                    $getFormContentValFunc("shou_kuan_xin_xi_EAHPE6", [])["branchName"] ?? ""
                );
            }

            $config = ConfigModel::getSingleConfig(
                "openShop",
                "ekb",
                function ($data) {
                    return json_decode($data);
                }
            );

            $specifications = EKuaiBaoRemote::getSpecificationsByIds($config->refundDecorationDeposit->documentTemplateId);
            if (empty($specifications) || empty($specifications["items"])) {
                throw new Exception("退款单单据模板id获取失败");
            }
            $specificationId = $specifications["items"][0]["id"];

            $feeTypeSpecifications = EKuaiBaoRemote::getFeeTypeSpecificationsByIds($config->refundDecorationDeposit->details->feeTypeId);
            if (empty($feeTypeSpecifications) || empty($feeTypeSpecifications["items"])) {
                throw new Exception("退款单单据费用模板id获取失败");
            }
            $feeTypeSpecificationId = $feeTypeSpecifications["items"][0]["expenseSpecificationId"];

            //获取供应商编码
            $supplierShopCodeRelModel = SupplierShopCodeRelModel::query()->where("shopCode",
                $shopInfo['shopList'][0]['shopCode'])->first();
            if (empty($supplierShopCodeRelModel)) {
                $supplierCode = "6805" . $shopInfo['shopList'][0]['shopCode'];
            } else {
                $supplierCode = $supplierShopCodeRelModel->supplierCode;
            }

            $requestFlowData = [
                "form" => [
                    "submitterId"       => $submitter["items"][0]["id"],
//                    "submitterId"       => "ID_3ihkmL8tzaw:ou_e72bf956a4c2954cc8e65a5d02e23d85",
                    //申请人
                    "expenseDate"       => time() * 1000,
                    "u_铺位号"             => (string)$shopInfo['shopList'][0]['shopCode'],
                    //申请日期
                    "title"             => "{$shopInfo['shopList'][0]['shopCode']} - {$shopInfo['shopList'][0]['name']}",
                    //摘要
                    "法人实体"              => $config->refundDecorationDeposit->legalPersonId,
                    //法人实体
                    "expenseDepartment" => $userDepartmentId,
                    //申请部门
                    "payeeId"           => $payeeInfo["id"],//收款信息
                    "u_供应商编码"           => $supplierCode,
                    "details"           => [
                        [
                            "feeTypeId"       => $config->refundDecorationDeposit->details->feeTypeId,
                            "specificationId" => $feeTypeSpecificationId,
                            "feeTypeForm"     => [
                                "amount"  => [
                                    "standard"        => (string)(($signOrderModel->contractRel->decorationDeposit > 0 ? $signOrderModel->contractRel->decorationDeposit : 500000) / $shopCount / 100),
                                    "standardUnit"    => "元",
                                    "standardScale"   => 2,
                                    "standardSymbol"  => "¥",
                                    "standardNumCode" => "156",
                                    "standardStrCode" => "CNY"
                                ],
                                "u_店铺名称"  => $shopInfo['shopList'][0]['name'],
                                "feeDate" => strtotime($getFormContentValFunc("jing_ying_shu_ju_19ls0T",
                                        formatDateYmd(time()))) * 1000
                            ]
                        ]
                    ],
                    //费用明细
                    "attachments"       => [$attachment],
                    //附件
                    "specificationId"   => $specificationId,
                    //模板id
                ]
            ];

            $responseFlowData = EKuaiBaoRemote::flowData($requestFlowData);

            EkbApplyHistoryModel::query()->insert([
                "orderNo"       => $orderNo,
                "shopCode"      => $shopInfo['shopList'][0]['shopCode'],
                "content"       => json_encode($requestFlowData, JSON_UNESCAPED_UNICODE),
                "flowId"        => $responseFlowData["flow"]["id"],
                "createdAt"     => time(),
                "refundAmount"  => ($signOrderModel->contractRel->decorationDeposit > 0 ? $signOrderModel->contractRel->decorationDeposit : 5000) / $shopCount,
                "approveResult" => json_encode([], JSON_UNESCAPED_UNICODE),
                "source"        => EkbApplyHistoryModel::SOURCE_0
            ]);

            try {
                $jsonPath = app_path("Remote/Feishu/FsTemplate") . "/AutoRefundDecorationSuccess.json";
                if (!$fileSystem->isFile($jsonPath)) {
                    throw new Exception("易快报 - 【 {$orderNo} 】【 获取消息模板失败 】");
                }
                $msgTemplateContents = $fileSystem->get($jsonPath);


                $msgContents = vsprintf($msgTemplateContents, [
                    $orderNo,
                    $supervisorUserInfo[0]["feishuUserId"],
                    $supervisorUserInfo[0]["username"],
                    $orderNo,
                    "{$shopInfo['shopList'][0]['shopCode']} - {$shopInfo['shopList'][0]['name']}",
                    (string)(($signOrderModel->contractRel->decorationDeposit > 0 ? $signOrderModel->contractRel->decorationDeposit : 500000) / $shopCount / 100),
                    formatDate(time())
                ]);
            } catch (Exception $exception) {
                SendFs::newRobot()->setTitleContent('易快报 - 获取消息配置失败', json_encode([
                    "orderNo"  => $orderNo,
                    "shopCode" => $shopInfo['shopList'][0]['shopCode'],
                    "shopName" => $shopInfo['shopList'][0]['name'],
                    "msg"      => $exception->getMessage()
                ]))->send();
            }

            try {
                SendFs::newRobot()
                      ->setCardMessageBody(json_decode($msgContents, true))
                      ->send();
            } catch (Exception $exception) {
                SendFs::newRobot()->setTitleContent('易快报 - 群消息推送失败', json_encode([
                    "orderNo"  => $orderNo,
                    "shopCode" => $shopInfo['shopList'][0]['shopCode'],
                    "shopName" => $shopInfo['shopList'][0]['name'],
                    "msg"      => $exception->getMessage()
                ]))->send();
            }

            try {
                FeishuMsgRemote::getInstance()->sendInteractiveMsg(
                    $msgContents, $supervisorUserInfo[0]["feishuUserId"]
                );
            } catch (Exception $exception) {
                SendFs::newRobot()->setTitleContent('易快报 - 个人消息推送失败', json_encode([
                    "orderNo"  => $orderNo,
                    "shopCode" => $shopInfo['shopList'][0]['shopCode'],
                    "shopName" => $shopInfo['shopList'][0]['name'],
                    "msg"      => $exception->getMessage()
                ]))->send();
            }

        } catch (Exception $exception) {
            if ($exception instanceof ResponseHttpException) {
                $content = json_decode($exception->getResponse()->getContent(), true);
                logException("退款装修保证金", $exception, array_merge(["orderNo" => $orderNo], $content), true, true);
            } else {
                logException("退款装修保证金", $exception, ["orderNo" => $orderNo], true, true);
            }

            try {
                $jsonPath = app_path("Remote/Feishu/FsTemplate") . "/AutoRefundDecorationFail.json";
                if (!$fileSystem->isFile($jsonPath)) {
                    throw new Exception("易快报 - 【 {$orderNo} 】【 获取消息模板失败 】");
                }

                $msgTemplateContents = $fileSystem->get($jsonPath);
                $shopInfo            = $shopInfo ?? [];
                $supervisorUserInfo  = $supervisorUserInfo ?? [];

                $shopCount   = $shopCount ?? 1;
                $msgContents = vsprintf($msgTemplateContents, [
                    $orderNo,
                    $supervisorUserInfo[0]["userId"] ?? "",
                    $supervisorUserInfo[0]["username"] ?? "",
                    $orderNo,
                    vsprintf("%s - %s",
                        [$shopInfo['shopList'][0]['shopCode'] ?? "", $shopInfo['shopList'][0]['name'] ?? ""]
                    ),
                    (string)(($signOrderModel->contractRel->decorationDeposit > 0 ? $signOrderModel->contractRel->decorationDeposit : 500000) / $shopCount / 100),
                    formatDate(time())
                ]);
            } catch (Exception $exception) {
                logException(
                    "易快报 - 获取失败消息模板失败",
                    $exception,
                    ["orderNo" => $orderNo, "msg" => $exception->getMessage()],
                    true, true
                );
            }

            try {
                SendFs::newRobot()
                      ->setCardMessageBody(json_decode($msgContents, true))
                      ->send();
            } catch (Exception $exception) {
                logException(
                    "易快报 - 推送群组消息失败",
                    $exception,
                    ["orderNo" => $orderNo, "msg" => $exception->getMessage()],
                    true, true
                );
            }


            try {
                if ($supervisorUserInfo && !empty($supervisorUserInfo[0]["feishuUserId"])) {
                    FeishuMsgRemote::getInstance()->sendInteractiveMsg(
                        $msgContents, $supervisorUserInfo[0]["feishuUserId"]
                    );
                }
            } catch (Exception $exception) {
                logException(
                    "易快报 - 推送个人消息失败",
                    $exception,
                    ["orderNo" => $orderNo, "msg" => $exception->getMessage()],
                    true, true
                );
            }

        }
    }


    /**
     * 筹备订单修改
     * @param $orderNo
     * @param $scheduledTime
     * @param $preparationStatus
     * @param $preparationReason
     * @param $preparationDesc
     * @param $pendingTermination
     * @param $log
     * @param $rmsUserId
     * @param $userName
     * @param $type
     * @param array $shopAttributes
     * @return array
     */
    public static function preparationUpdate(
        $orderNo,
        $scheduledTime,
        $preparationStatus,
        $preparationReason,
        $preparationDesc,
        $pendingTermination,
        $log,
        $rmsUserId,
        $userName,
        $type,
        array $shopAttributes = []
    ): array
    {
        $orderSignInfo = OpenShopSignOrderModel::orderDetail($orderNo, false, false, false,
            false, false, true, false, false,
            false, false, true, false, true)->getIterator()->current();// 订单信息
        if ($scheduledTime && !($orderSignInfo->startBusinessRel && $orderSignInfo->startBusinessRel->startBusinessTime)) {//预计开业时间 检查门店开业后，预计开业时间同步为开业时间，且不可修改
            $update = OpenShopSiteLocationModel::query()
                ->where('orderNo', $orderNo)
                ->where('openTime', '!=', strtotime($scheduledTime))
                ->update(['openTime' => strtotime($scheduledTime)]);
            //开店 - 选址阶段主表
            $update = OpenShopLocationModel::query()
                ->where('orderNo', $orderNo)
                ->where('openTime', '!=', strtotime($scheduledTime))
                ->update(['openTime' => strtotime($scheduledTime)]);
            if ($update) {
                // 订单日志
                $changes = json_encode(
                    [
                        [
                            "theme"      => "修改预计开业时间",
                            "changeType" => ChangeSupport::CHANGE_TYPE_SINGLE_INSERT,
                            "data"       => [
                                [
                                    "key"         => "text",
                                    "beforeValue" => $orderSignInfo->siteLocationRel && $orderSignInfo->siteLocationRel->openTime ? date('Y-m-d', $orderSignInfo->siteLocationRel->openTime) : "-",
                                    "afterValue"  => $scheduledTime,
                                    "beforeText"  => $orderSignInfo->siteLocationRel && $orderSignInfo->siteLocationRel->openTime ? date('Y-m-d', $orderSignInfo->siteLocationRel->openTime) : "-",
                                    "afterText"   => $scheduledTime,
                                    "type"        => ChangeSupport::FILED_TYPE_DATE_YMD,
                                    "description" => '修改预计开业时间'
                                ]
                            ]
                        ]
                    ], JSON_UNESCAPED_UNICODE
                );
                OpenShopSignOrderLogModel::logInsert(
                    $orderSignInfo->id,
                    OpenShopSignOrderLogModel::SKIP_STEP_UPDATE_SCHEDULED_TIME,
                    $userName,
                    $rmsUserId,
                    $changes
                );
            }
        }
        if ($preparationStatus) {//筹备状态 1-正常 2-异常
            $tagType = $preparationStatus == 1 ? OpenShopOrderTagsMappingModel::TAG_TYPE_1 : OpenShopOrderTagsMappingModel::TAG_TYPE_2;
            self::updateTags(
                $orderNo, $orderSignInfo->id, $tagType, [OpenShopOrderTagsMappingModel::TAG_TYPE_1, OpenShopOrderTagsMappingModel::TAG_TYPE_2],
                $rmsUserId, $userName, $type, $preparationReason, $preparationDesc
            );
        }
        if ($pendingTermination) {//门店待解约状态  1-正常 2-待解约 3-沉默客户  17 正常客户（A）- 定向选址 18 沉默客户（A）- 高流失风险
            switch ($pendingTermination) {
                case 1:
                    $tagType = OpenShopOrderTagsMappingModel::TAG_TYPE_14;
                    break;
                case 2:
                    $tagType = OpenShopOrderTagsMappingModel::TAG_TYPE_15;
                    break;
                case 3:
                    $tagType = OpenShopOrderTagsMappingModel::TAG_TYPE_16;
                    break;
                default:
                    $tagType = $pendingTermination;
            }
            self::updateTags(
                $orderNo, $orderSignInfo->id, $tagType,
                [
                    OpenShopOrderTagsMappingModel::TAG_TYPE_14, OpenShopOrderTagsMappingModel::TAG_TYPE_15, OpenShopOrderTagsMappingModel::TAG_TYPE_16
                    , OpenShopOrderTagsMappingModel::TAG_TYPE_17, OpenShopOrderTagsMappingModel::TAG_TYPE_18
                ],
                $rmsUserId, $userName, $type
            );
        }
        if ($log && isset($log['desc'])) {//筹备日志
            if ($orderSignInfo) {
                if ($type == 'siteLocation') {//选址中状态--同步订单日志
                    $data[] = [
                        "key"         => "text",
                        "beforeValue" => "",
                        "afterValue"  => $log['desc'],
                        "beforeText"  => "",
                        "afterText"   => $log['desc'],
                        "type"        => ChangeSupport::FILED_TYPE_STRING,
                        "description" => '修改选址中状态说明'
                    ];
                    if (isset($log['img']) && is_array($log['img'])) {
                        $data[] = [
                            "key"         => "url",
                            "beforeValue" => '',
                            "afterValue"  => $log['img'],
                            "beforeText"  => '',
                            "afterText"   => $log['img'],
                            "type"        => ChangeSupport::FILED_TYPE_PUBLIC_PICTURE,
                            "description" => "修改选址中图片"
                        ];
                    }
                    // 订单日志
                    $changes = json_encode(
                        [
                            [
                                "theme"      => "修改选址中状态说明",
                                "changeType" => ChangeSupport::CHANGE_TYPE_SINGLE_INSERT,
                                "data"       => $data,
                            ]
                        ], JSON_UNESCAPED_UNICODE
                    );
                    OpenShopSignOrderLogModel::logInsert(
                        $orderSignInfo->id,
                        OpenShopSignOrderLogModel::SKIP_STEP_UPDATE_SITE_LOCATION_INFO,
                        $userName,
                        $rmsUserId,
                        $changes
                    );
                } else {
                    $createLog = OperateLogModel::add(
                        OperateLogModel::BUSINESS_OPEN_SHOP_PREPARATION,
                        $orderSignInfo->id,
                        $orderSignInfo->id,
                        '添加筹备日志',
                        $log['desc'] ?? '',
                        OperateLogModel::STATUS_OK,
                        $rmsUserId,
                    );
                    if ($createLog && isset($log['img']) && is_array($log['img'])) {//保存资源图片
                        foreach ($log['img'] as $file) {
                            ResourcesModel::moduleBusinessResourcesBuild(
                                ResourcesModel::MODULE_TYPE_OPEN_SHOP,
                                ResourcesModel::BUSINESS_OPEN_SHOP_PREPARATION,
                                'LogImg',
                                (int)$createLog->id,
                                ltrim(parse_url($file, PHP_URL_PATH), '/')
                            );
                        }
                        ResourcesModel::moduleBusinessResourcesSave();
                    }
                }
            }
        }

        // 修改门店属性
        $shopId = $orderSignInfo->progressRel->shopId ?? 0;
        if ($shopId && $shopAttributes) {
            $siteLocationData = OpenShopSiteLocationModel::query()
                ->whereIn('source', [OpenShopSiteLocationModel::SOURCE_OPEN_SHOP, OpenShopSiteLocationModel::SOURCE_HOUSING])
                ->where('orderNo', $orderNo)->first();
            if($siteLocationData){
                $shopAttributeData = CommonService::getShopAttributeData();// rms门店属性配置
                $updateDataLog     = [];

                // 先修改开店 关联选址表单数据
                $updateSiteLocation = [];
                if (isset($shopAttributes['shopType']) && $siteLocationData['shopType'] != $shopAttributes['shopType']) {// 店型
                    $updateSiteLocation['shopType'] = $shopAttributes['shopType'];
                    $res = self::getUpdateShopAttributeText($shopAttributeData, SiteLocationEnum::CATEGORY_ID_2, $shopAttributes['shopType'], $siteLocationData['shopType']);

                    $updateDataLog[] = [
                        'key'         => 'text',
                        'beforeValue' => $res['oldText'],
                        'beforeText'  => $res['oldText'],
                        'afterValue'  => $res['newText'],
                        'afterText'   => $res['newText'],
                        'type'        => ChangeSupport::FILED_TYPE_STRING,
                        'description' => '修改筹备信息-店型'
                    ];
                }
                if (isset($shopAttributes['siteSelection']) && $siteLocationData['siteSelection'] != $shopAttributes['siteSelection']) {// 选址场景
                    $updateSiteLocation['siteSelection'] = $shopAttributes['siteSelection'];
                    $res = self::getUpdateShopAttributeText($shopAttributeData, SiteLocationEnum::CATEGORY_ID_3, $shopAttributes['siteSelection'], $siteLocationData['siteSelection']);

                    $updateDataLog[] = [
                        'key'         => 'text',
                        'beforeValue' => $res['oldText'],
                        'beforeText'  => $res['oldText'],
                        'afterValue'  => $res['newText'],
                        'afterText'   => $res['newText'],
                        'type'        => ChangeSupport::FILED_TYPE_STRING,
                        'description' => '修改筹备信息-选址场景'
                    ];
                }
                if (isset($shopAttributes['sellingCategory']) && $siteLocationData['sellingCategory'] != $shopAttributes['sellingCategory']) {// 售卖品类
                    $updateSiteLocation['sellingCategory'] = $shopAttributes['sellingCategory'];
                    $res = self::getUpdateShopAttributeText($shopAttributeData, SiteLocationEnum::CATEGORY_ID_4, $shopAttributes['sellingCategory'], $siteLocationData['sellingCategory']);

                    $updateDataLog[] = [
                        'key'         => 'text',
                        'beforeValue' => $res['oldText'],
                        'beforeText'  => $res['oldText'],
                        'afterValue'  => $res['newText'],
                        'afterText'   => $res['newText'],
                        'type'        => ChangeSupport::FILED_TYPE_STRING,
                        'description' => '修改筹备信息-售卖品类'
                    ];
                }
                if (isset($shopAttributes['menuLevel']) && $siteLocationData['menuLevel'] != $shopAttributes['menuLevel']) {// 产品定价
                    $updateSiteLocation['menuLevel'] = $shopAttributes['menuLevel'];
                    $res = self::getUpdateShopAttributeText($shopAttributeData, SiteLocationEnum::CATEGORY_ID_11, $shopAttributes['menuLevel'], $siteLocationData['menuLevel']);

                    $updateDataLog[] = [
                        'key'         => 'text',
                        'beforeValue' => $res['oldText'],
                        'beforeText'  => $res['oldText'],
                        'afterValue'  => $res['newText'],
                        'afterText'   => $res['newText'],
                        'type'        => ChangeSupport::FILED_TYPE_STRING,
                        'description' => '修改筹备信息-产品定价'
                    ];
                }
                if (isset($shopAttributes['posLine']) && $siteLocationData['posLine'] != $shopAttributes['posLine']) {// 点餐动线
                    $updateSiteLocation['posLine'] = $shopAttributes['posLine'];
                    $res = self::getUpdateShopAttributeText($shopAttributeData, SiteLocationEnum::CATEGORY_ID_6, $shopAttributes['posLine'], $siteLocationData['posLine']);

                    $updateDataLog[] = [
                        'key'         => 'text',
                        'beforeValue' => $res['oldText'],
                        'beforeText'  => $res['oldText'],
                        'afterValue'  => $res['newText'],
                        'afterText'   => $res['newText'],
                        'type'        => ChangeSupport::FILED_TYPE_STRING,
                        'description' => '修改筹备信息-点餐动线'
                    ];
                }
                if ($updateSiteLocation) {
                    OpenShopSiteLocationModel::query()
                        ->whereIn('source', [OpenShopSiteLocationModel::SOURCE_OPEN_SHOP, OpenShopSiteLocationModel::SOURCE_HOUSING])
                        ->where('orderNo', $orderNo)
                        ->update($updateSiteLocation);
                    RmsShopRemote::updateShopAttribute($shopId, array_merge($shopAttributes, ['rmsUserId' => $rmsUserId])) ?? [];
                }

                // 订单日志
                $changes = json_encode(
                    [
                        [
                            'theme'      => '修改筹备信息',
                            'changeType' => ChangeSupport::CHANGE_TYPE_SINGLE_UPDATE,
                            'data'       => $updateDataLog,
                        ]
                    ], JSON_UNESCAPED_UNICODE
                );
                OpenShopSignOrderLogModel::logInsert(
                    $orderSignInfo->id,
                    OpenShopSignOrderLogModel::SKIP_STEP_UPDATE_PREPARATION_INFO,
                    $userName,
                    $rmsUserId,
                    $changes
                );
            }
        }
        return [];
    }

    /**
     * 筹备订单日志
     * @param string $orderNo
     * @param int $orderId
     * @param int $limit
     * @return array
     */
    public static function preparationLog(string $orderNo, int $orderId = 0, int $limit = 0): array
    {
        if (!$orderId && $orderNo) {
            $orderSignInfo = OpenShopSignOrderModel::orderDetail($orderNo)->getIterator()->current();                             // 订单信息
            $orderId       = $orderSignInfo->id;
        }
        return OperateLogModel::getData(OperateLogModel::BUSINESS_OPEN_SHOP_PREPARATION, $orderId, $orderId, 'desc', $limit)
            ->map(
                function ($log) {
                    $resourcesList = [];
                    collect($log->resourcesRel)->each(
                        function (ResourcesModel $resourcesModel) use (&$resourcesList) {
                            $resourcesList[] = picturePath($resourcesModel->url);
                        }
                    )->toArray();
                    return [
                        'id'         => $log->id,
                        'userId'     => $log->userId,
                        'userName'   => $log->userName ? $log->userName : "系统",
                        'logId'      => $log->logId,
                        'logName'    => $log->logName,
                        'logContent' => $log->logContent,
                        'createdAt'  => $log->createdAt->toDateTimeString(),
                        'img'        => $resourcesList,//资源数据
                    ];
                }
            )->toArray();
    }

    /**
     * 筹备标签统一处理
     * @param $orderNo
     * @param $orderId
     * @param $tagTypeUpdate
     * @param $originTagTypes
     * @param $rmsUserId
     * @param $userName
     * @param $type
     * @param string $preparationReason
     * @param string $preparationDesc
     * @return array
     */
    public static function updateTags($orderNo, $orderId, $tagTypeUpdate, $originTagTypes, $rmsUserId, $userName, $type, $preparationReason = '', $preparationDesc = ''): array
    {
        $beforeValue = $afterValue = '';
        $getTagsInfo = OpenShopOrderTagsMappingModel::getInfoByOrderNo($orderNo, $originTagTypes);
        if ($getTagsInfo) {
            if ($getTagsInfo->tagId == $tagTypeUpdate && $getTagsInfo->remark == $preparationReason && $getTagsInfo->desc == $preparationDesc) {
                return [];
            }
            /*if ($tagTypeUpdate == OpenShopOrderTagsMappingModel::TAG_TYPE_1) {//筹备正常-清理异常原因
                $preparationReason = $preparationDesc = '';
            }*/
            $beforeValue = OpenShopOrderTagsMappingModel::TAG_TYPE_MAP_TEXT[$getTagsInfo->tagId] ?? "";
            OpenShopOrderTagsMappingModel::query()
                ->where('id', $getTagsInfo->id)
                ->update(
                    [
                        'remark' => $preparationReason,
                        'desc'   => $preparationDesc,
                        'tagId'  => $tagTypeUpdate,
                    ]
                );
        } else {
            OpenShopOrderTagsMappingModel::addTags($orderNo, $tagTypeUpdate, $preparationDesc, $preparationReason);
        }

        if ($type == 'siteLocation') {//选址中状态
            $logType = OpenShopSignOrderLogModel::SKIP_STEP_UPDATE_SITE_LOCATION;
        } else {
            $logType = OpenShopSignOrderLogModel::SKIP_STEP_UPDATE_PREPARATION_INFO;//筹备中
        }
        switch ($tagTypeUpdate) {
            case OpenShopOrderTagsMappingModel::TAG_ABNORMAL_1:
            case OpenShopOrderTagsMappingModel::TAG_ABNORMAL_2:
                $title = '修改门店状态';
                break;
            case OpenShopOrderTagsMappingModel::TAG_TYPE_14:
            case OpenShopOrderTagsMappingModel::TAG_TYPE_15:
            case OpenShopOrderTagsMappingModel::TAG_TYPE_16:
            case OpenShopOrderTagsMappingModel::TAG_TYPE_17:
            case OpenShopOrderTagsMappingModel::TAG_TYPE_18:
                $title = OpenShopOrderTagsMappingModel::TAG_TYPE_MAP_TEXT[$tagTypeUpdate] ?? "";
                break;
            default:
                $title = "修改门店信息";
        }
        $afterValue = OpenShopOrderTagsMappingModel::TAG_TYPE_MAP_TEXT[$tagTypeUpdate] ?? "";
        $data = [
            [
                "key"         => "text",
                "beforeValue" => $beforeValue,
                "afterValue"  => $afterValue,
                "beforeText"  => $beforeValue,
                "afterText"   => $afterValue,
                "type"        => ChangeSupport::FILED_TYPE_STRING,
                "description" => $title
            ]
        ];
        if ($preparationDesc) {
            $data[] = [
                "key"         => "text",
                "beforeValue" => '',
                "afterValue"  => $preparationDesc,
                "beforeText"  => '',
                "afterText"   => $preparationDesc,
                "type"        => ChangeSupport::FILED_TYPE_STRING,
                "description" => "描述说明"
            ];
        }
        // 订单日志
        $changes = json_encode(
            [
                [
                    "theme"      => $title,
                    "changeType" => ChangeSupport::CHANGE_TYPE_SINGLE_INSERT,
                    "data"       => $data,
                ]
            ], JSON_UNESCAPED_UNICODE
        );
        OpenShopSignOrderLogModel::logInsert(
            $orderId,
            $logType,
            $userName,
            $rmsUserId,
            $changes
        );

        return [];
    }

    /**
     * 查询飞书用户和一级部门
     * @return mixed
     */
    public static function getFeishuUserDepartmentList()
    {
        return Cache::remember('openShop:getFeishuUserDepartmentList', getSwitchCacheTime(600), function () {
            $index = 1;
            $list  = KmsUser::query()->where('isResigned', 0)
                            ->select([
                                'id',
                                'name',
                                'nickname',
                                'userId',
                                'rootDepartmentName',
                                'isResigned',
                                'isActivated',
                                'isExited',
                                'groupParentDepartment'
                            ])
                            ->get()->map(function (KmsUser $kmsUser) {
                    if ($kmsUser->rootDepartmentName == "分公司") {
                        $groupDepartment = explode("/", $kmsUser->groupParentDepartment);
                        if (count($groupDepartment) >= 2) {
                            $kmsUser->rootDepartmentName = $groupDepartment[1];
                        }
                    }
                    return $kmsUser;
                })->groupBy("rootDepartmentName")->map(function ($group, $key) use (&$index) {
                    $index++;
                    return [
                        "children" => $group->map(function (KmsUser $kmsUser) {
                            return [
                                "label" => vsprintf("%s(%s)", [$kmsUser->name, $kmsUser->nickname]),
                                "value" => $kmsUser->userId
                            ];
                        }),
                        "label"    => $key,
                        "value"    => $index
                    ];
                })->values();

            $outOrganization = ConfigService::config('openShop', 'outOrganization')['outOrganization'];
            $list            = $list->add($outOrganization)->toArray();

            return $list;
        });

//        return Cache::remember(
//            'openShop:getFeishuUserDepartmentList', getSwitchCacheTime(86400), function () {
//            $data = [];
//            collect(
//                (new RmsUserApi())->getFsUsers(
//                    '',
//                    ['id', 'name', 'nickname', 'userId', 'rootDepartmentName', 'isResigned', 'isActivated', 'isExited']
//                )['data']['lists'] ?? []
//            )
////                ->where('isResigned', 0)//是否离职
////                ->where('isActivated', 1)//是否激活
////                ->where('isExited', 0)//是否主动退出，主动退出一段时间后用户会自动转为已离职
//                ->where('rootDepartmentName', '!=', '')
//                ->map(
//                    function ($item) use (&$data) {
//                        $children = [
//                            'label' => $item['name'] . '(' . $item['nickname'] . ')',
//                            'value' => $item['userId'],
//                        ];
//                        if (isset($data[$item['rootDepartmentName']])) {
//                            $data[$item['rootDepartmentName']]['children'][] = $children;
//                        } else {
//                            $data[$item['rootDepartmentName']] = [
//                                'label'    => $item['rootDepartmentName'],
//                                'value'    => $item['id'],
//                                'children' => [$children],
//                            ];
//                        }
//                    }
//                )->toArray();
//            return array_values($data);
//        }
//        );
    }




    public static function sendVoidTheContract($content)
    {
        if ('prod' == config('app.env')) {
            //选址培训
            $robot = [
                'url'      => 'https://open.feishu.cn/open-apis/bot/v2/hook/e0074470-dbe4-4d51-836f-1cee3d0f1804',
                'urlToken' => 'e0074470-dbe4-4d51-836f-1cee3d0f1804',
                'secret'   => 'E6IGHT0Mzta3l5rAJ4RA4c'
            ];
        } else {
            //测试
            $robot = [
                'url'      => 'https://open.feishu.cn/open-apis/bot/v2/hook/e27b9ae1-d1e9-4346-9988-bfe353a0f846',
                'urlToken' => 'e27b9ae1-d1e9-4346-9988-bfe353a0f846',
                'secret'   => '5mWdHKVBSeYYMhcdtlsKlc'
            ];
        }

        $res = Factory::feiShu()
            ->setToken($robot['urlToken'])
            ->setSecret($robot['secret'])
            ->setMessage(new CardMessage($content))
            ->send();
        Log::info('订单作废通知推送结果' . json_encode($res, JSON_UNESCAPED_UNICODE));
    }


    /**
     * 超时未支付作废订单
     * @return void
     * @throws Exception
     */
    public static function noPayTimeOutToClose(): bool
    {
        $data =  OpenShopSignOrderModel::query()
                                      ->with("contractTimeOutNoPayRel")
                                      ->where('payStatus', SignOrderEnum::PAY_STATUS_NULL)
                                      ->where('status', SignOrderEnum::ORDER_STATUS_OK)
                                      ->where("createdAt",">",strtotime(OpenShopContractTemplateModel::ONLINE_DATA_TIME_V1))
                                      ->get();
        if (!empty($data)) {
            $data = $data->toArray();
            foreach ($data as $k => $value) {

                if (!empty($value['contract_time_out_no_pay_rel'])) {
                    try {
                        // 作废订单
                        self::invalidOrder(0, (object)[
                            'orderNo'        => $value['orderNo'],
                            'invalidateType' => OpenShopSignOrderModel::INVALIDATE_TYPE_5,
                            'reason'         => "超时未支付",
                            'contractType'   => 0
                        ]);

                        // 推送卡片消息
                        $card = [
                            "header"   => [
                                "title" => [
                                    "tag"     => "plain_text",
                                    "content" => '加盟订单超时未支付作废'
                                ]
                            ],
                            'elements' => [
                                [
                                    "tag"     => "markdown",
                                    "content" => "订单号：" . $value['orderNo']
                                ],
                                [
                                    "tag"     => "markdown",
                                    "content" => "招商经理：" . $value['investmentManagerName']
                                ]
                            ],
                        ];

                        // 推送卡片消息
                        BuildFs::newRobot(SendFs::ROBOT_BUSINESS_OPEN_SHOP_SIGN_ORDER_CLOSE, BuildFs::MSG_TYPE_CARD)
                               ->setCardContent($card)
                               ->send();

                    } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) {

                    }
                }

            }
        }

        return true;

    }

    /**
     * 修改筹备信息-门店属性时获取前后对应的值
     * @param array $shopAttributeData
     * @param int $categoryId
     * @param string $newId
     * @param string $oldId
     * @return string[]
     */
    public static function getUpdateShopAttributeText(array $shopAttributeData, int $categoryId, string $newId, string $oldId): array
    {
        $newText  = $oldText = [];
        $newArr   = explode(',', $newId);
        $oldIdArr = explode(',', $oldId);
        $temp     = collect($shopAttributeData)->where('id', $categoryId)->first();
        if ($temp) {
            foreach ($temp['value'] as $v) {
                if (in_array($v['id'], $newArr)) {
                    $newText[] = $v['name'];
                }
                if (in_array($v['id'], $oldIdArr)) {
                    $oldText[] = $v['name'];
                }
            }
        }
        return [
            'newText' => implode(',', $newText),
            'oldText' => implode(',', $oldText),
        ];
    }
}
